Behat, Mink and Docker

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:

  1. A Web container running nginx (name: bdd_web_1)
  2. A PHP container running php-fpm (name: bdd_php_1)
  3. A DB container running MySQL (name: bdd_db_1)
  4. 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.