Apr 9, 2014
Behat is a runner that devours Gherkin specifications and maps them to context classes to execute whatever code you want. Mink is an abstraction layer over several browser drivers and emulators that unifies their different APIs under one consistent API. You can use them together, but you don’t have to. Actually, you better not be doing this at all.
I took part in development of several projects where we either used Behat without Mink, Mink without Behat, or both Behat and Mink but they didn’t know about each other.
When it was just Behat on a project, it was used to drive the development and verification of the domain logic. Since domain logic rarely — if ever — depends on a UI, verification was done on the domain level without touching UI at all.
When it was just Mink, it was run by PHPUnit. Those were tests, not specifications. Since BDD is about communication and I didn’t need to communicate on and write UI specifications, I didn’t need Behat. All I needed were tests to drive the development of and catch regressions in the UI.
When there were both Behat and Mink on a project, it was a combination of both the approaches described above. Behat was used to run the development and verification of the domain logic and Mink run by PHPUnit was used to drive the development of and catch regressions in the UI.
PHPUnit is still a great test runner that does its job. Behat does not replace PHPUnit. They just solve different problems. I use PHPUnit for unit, integration, UI, and API testing. I use Behat to run verifications of domain logic.
Why do I say you should avoid using Behat and Mink together? Because it causes at least two problems.
First, if you’re doing BDD properly and do not tie domain specifications to UI but still verify domain through UI, domain verifications are dependent on UI and will falsely fail when UI is broken even though domain code is correct. It will also make verifications unnecessary slow because of running them through UI. If you would verify domain code directly, you wouldn’t suffer from these problems.
Second, it leads to awful scenarios like this:
1 2 3 4 5 6 7 8 9 Scenario: Successful login Given a user "Elnur" with password "sw0rdf1sh" And I am on "/app_test.php/login" And I fill in "User name" with "Elnur" And I fill in "Password" with "sw0rdf1sh" When I press "Log in" Then the status code should be 200 And I should be on "/app_test.php/home" And I should see "Welcome, Elnur"
It’s awful because it fails as a communication medium between stakeholders and developers. And if it was written just for developers, you could as well write a test with PHPUnit driving Mink and avoid the overhead of text-to-code translation.
There is an exception where you might need to use them together. It happens when you have to specify something that makes sense only in the UI itself, for instance, UI specific flows like wizards.
Even though you could test them with technical tools like PHPUnit, if the problems are in communication between stakeholders and developers, you could do BDD and use Behat and Mink together. But these should be separate specifications that don’t have anything to do with domain ones. They should be separated even in the specifications layout.
But before you do that, think hard on whether you really need to specify UI specific stuff in the form of BDD. In most cases, BDD should be used to specify domain logic, while UI is being figured by the development team on their own because they know better how to do that.
Like I wrote in the beginning, I don’t know what the source of this confusion is. Maybe it was caused by the fact that both Behat and Mink were created by the same people and are featured together on the same behat.org domain. Maybe it was the cookbook article called Developing Web Applications with Behat and Mink on the same domain showcasing the same awful approach.
I don’t know what caused the confusion, but I see it running very deep in the community. One of the testimonies to that is the Page Object Extension written for Behat, when it should have been written for Mink instead.
Even though the author of Cucumber — the tool that Behat is a clone of — wrote the post The Training Wheels Came Off more than two years ago, the PHP community still has some catching up to do. I hope this post will help with that.