Behat, Mink and Docker
I’ve been porting across one of the live demos I do (that’s a Symfony project to demonstrate BDD & Behat stuff) from the built-in PHP web-server and a locally-hosted MySQL Database to a Docker configuration. I had some struggles with getting my Web UI Behat suite to work correctly inside the PHP container, here’s what should be done.
Using the built in PHP web-server and a locally hosted MySQL database was simple and worked, but I wanted to experiment a bit. Live life on the edge! What’s crazier than a live demo? A live demo relying on Docker! Woo!
The setup:
I have 4 containers:
- A Web container running nginx (name:
bdd_web_1
) - A PHP container running php-fpm (name:
bdd_php_1
) - A DB container running MySQL (name:
bdd_db_1
) - A DB-Data container that’s a persistent volume that MySQL can connect to so I don’t lose my DB each time I
docker-compose down
(name:bdd_dbdata_1
)
I have a number of suites in Behat. A domain
suite that tests the PHP objects at the core of the thing I’m testing, as well as a webui
suite that tests the same feature file through a browser using different contexts to the domain suite (see: “Avoiding implementation in feature files” for a bit more info)
Testing the domain suite worked like this:
docker exec -it bdd_php_1 /app/bin/behat --suite=domain -c /app/behat.yml
Tests passed fine (Note: though docker exec
returned a status code of 129
, even though tests passed locally - it seems to be something with the -t
flag on it)
The reason they passed fine is because under the surface, all it’s doing is making sure some objects work correctly together, which only uses PHP (and that’s what the container it was being run in is for)
The problem
When it came to my UI suite, I ran:
docker exec -it bdd_php_1 /app/bin/behat --suite=webui -c /app/behat.yml
Running that gave me errors about connections being refused:
cURL error 7: Failed to connect to 127.0.0.1 port 8000: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html) (GuzzleHttp\Exception\ConnectException)
My Behat configuration was the following (as this is what I was using before I moved to Docker):
default:
extensions:
Behat\MinkExtension:
base_url: 'http://127.0.0.1:8000/app_test.php/'
So why were my tests failing at connecting?
The base_url
parameter still referenced 127.0.0.1 - the container that the tests are being run in (bdd_php_1
) doesn’t have a web server, I could start it with /app/bin/console server:start
- but I have a proper web server now, I should use that!
With docker, you can reference other containers by their name when doing things like accessing them with curl, so if I ran:
docker exec -it bdd_php_1 curl bdd_web_1
It would work fine, I’d get the HTML back for the app because Docker performs magic and knows how to resolve bdd_web_1
to the correct container.
The solution
The solution was to do the following:
default:
extensions:
Behat\MinkExtension:
base_url: 'http://bdd_web_1/app_test.php/'
Now it’d use the correct URL. The Docker magic that connects containers together (I still don’t fully understand it all yet, I’m just getting started with Docker) works and Mink can test the UI through a browser! All this even though the bdd_php_1
container isn’t running a webserver, that’s the job of the bdd_web_1
container!
So now when we run our webui
suite with:
docker exec -it bdd_php_1 /app/bin/behat --suite=webui -c /app/behat.yml
It properly runs the tests against the correct URL and they all passed (I still got the 129
return code like before, but that’s another issue that I’m investigating at the minute)
Originally I thought using external_links
in my docker-compose.yml
was the solution, but I don’t think I need that anymore.