I recently got PHPUnit and Laravel Dusk tests to pass for AIP Demos when either running Dusk in an OS with a graphical environment or one that is using xvfb (X virtual frame buffer). I also got them to run on the container created by TravisCI. It took quite a bit of trial and error, but that badge of an image above is a badge of honor. I had to slay quite a few more intimidating dragons than the pat on the back one deserves for launching, say, Atlassian sites or something.
The hardest part of these tests was getting Laravel Dusk to work in a pure command-line environment, namely the docker container I use to deploy it and the TravisCI container. Take a look at the docker container that AIP Demos is deployed on. It is based on the php:apache docker container that uses Debian version 8 (jessie). I had to add a few packages: xvfb
is the virtualized X environment needed to allow a browser such as Chromium to be launched by the chromedriver
command used by Laravel Dusk. libgconf-2-4
and libfontconfig
are dependencies that chromium
needs. And of course, you’ll want the chromium
package. Some Linux distros, like Ubuntu, might have this as chromium-browser
instead.
Next, I had to consult the repo of a savvy web server admin / developer to get things working from here. It seems that the chromedriver
program will try to either start google-chrome
or chromium-browser
. For the php:apache
container, installing google-chrome-stable
from Google doesn’t seem to do the trick. Chromium has to be started with the --no-sandbox
flag in order to properly accommodate chromedriver
. A good way to do this is by symlinking the google-chrome
and chromium-browser
commands to a script, such as the one called xvfb-chromium created by this excellent user, which I only slightly customized. This can be done in a Dockerfile that does the following: copies the xvfb-chromium
script to either /usr/bin
or a less controversial place in the container server’s path, makes sure the script is executable, and creates the symlinks. I also decided to have Xvfb run on DISPLAY :0
instead of :99
, which seemed to cause fewer problems. By far, the trickiest part was finding out how to make chromedriver
, started by Dusk, launch the Chromium browser in a way in which Dusk was satisfied, and I have okaufmann to thank.
One caveat of this approach is that after php artisan dusk
is ran, the chromium
process is still left running. Since a DuskTestCase
seems to only reset a database after the php artisan dusk
command finishes, I needed to run several such commands for my various tests that required an empty DB, which results in several leftover chromium
processes. I added a static tearDownAfterClass method to DuskTestCase
that gets the PIDs of the chromium
program and terminates them if the web app is running on Linux and /usr/bin/xvfb-chromium
is present. tearDownAfterClass
comes with PHPUnit and is ran after all the test methods in a class finish. It will also terminate the Xvfb process.
This setup finally got Laravel Dusk to successfully run tests in the docker container. The next challenge was making it work on TravisCI.
To make this happen, I ended up configuring the container with this .travis.yml, which basically came from one shared on laravel-news.com that should be in the docs and hopefully will be soon. The key was to use the Ubuntu “trusty” container with a modern version of PHP, making sure composer install
is ran, starting xvfb
from an init.d
script that would appear to be available in this version of Ubuntu, running chromedriver
manually in the background, manually copying .env.testing
to .env
, setting an appropriate DISPLAY environment variable, and starting the built-in PHP web server. Another crucial thing to remember is to set APP_URL
in .env.testing
to a URL that the web server will run on, which is typically //localhost:8000
.
These are the secrets to my success. I hope you might find this experience helpful.