PHPUnit vs Behat

On my site, I only have one feature made with specific code, sending a notification email when a comment is created. The rest of the specific code corresponds to the theme and content migrations (when I migrated from Drupal 7).

Although this is a simple feature, I thought it would be interesting to test the same functionality with 2 approaches, one via PHPUnit and the other via Behat to have points of comparison.

To share the code I've created, I've created the following snippet: https://gitlab.com/-/snippets/2100504

PHPUnit

See this article for an explanation of PHPUnit tests and how they implement tests in Drupal.

To implement the email functionality, I implemented a hook_comment_entity_insert() to act when a comment is created.

Since this hook is triggered both for a comment created via code and via a comment form, I ran 2 tests (in different files because with different setup) :

  • testCommentMailSend() : to test when a comment is created regardless of the source
  • testCommentFormMailSend() : to test when submitting a comment form

For the second test, as the comment created is not available as a variable directly, it has to be loaded manually. I could have used the entityTypeManager service, but I preferred to use what I had available by following front-end behaviour, i.e. being redirected to a URL with the comment number as a parameter.

Behat

Behat is a " behaviour-driven " PHP testing framework. The tests are written in Gherkin, a test writing language that can be understood by the business, the tests follow the following structure :

  • as X
  • if I do Y
  • then I expect Z

A simple configuration for Behat is to use the Goutte browser which is a PHP headless browser, it won't interpret the JS.

In behat, the test is about fifteen lines long, understandable by anyone.

The difficulties encountered were :

  • adapting the Behat configuration, file behat.yml :
    • change the names of the regions I use on my theme (Bootstrap)
    • change the selectors for posts and some text because translated into French
  • Gout edge effects, as the browser does not interpret JS :
    • I use the Antibot module as anti-spam, yet it considers that if the JS is not interpreted, it is a robot. The most complicated part was understanding why I was getting errors where a test on a site without Antibot worked. Once the problem was identified, it was a simple matter to disable the protection in the tests.
    • even though the email test worked, I wanted to check that the email capture confirmation message worked. Now I use Big Pipe on my site, and although Big Pipe is able to adapt if the browser doesn't interpret the JS, Goutte doesn't explicitly send the information that the JS isn't interpreted. As a result, it's impossible to test a Drupal message. There is this issue in progress on the Drupal extension for Behat.

Comparisons

Behat

Once the Behat configuration is ready, if it weren't for the JS-related side-effects, writing tests is fairly fluid.

Where PHPUnit tests are aimed at developers, Behat tests can be written by other profiles.

Some points of attention:

  • if you ever need to debug, you'll need to edit the Behat code to be able to access the error messages
  • I just used the features available in Behat and the Drupal extension for Behat, if there is a need to code Behat features specific to a project, then a developer profile will be required
  • the strings in the tests are in French, on a multilingual site this can complicate detecting the origin of a problem. Tests can fail because the imported translation is no longer the correct one, or because there is actually another problem

PHPUnit

As much as writing the test in Behat is simple, I haven't exactly tested the same points as with PHPUnit.

With PHPUnit tests, I could easily test generated variables and therefore test the complete content of the email sent. This would have been complex to my knowledge without a dedicated feature.

Execution time

Execution time taken from running tests in Gitlab CI.

PHPUnit : 122s

  • testCommentFormMailSend() : 99s
  • testCommentMailSend() : 22s

Behat : 5s

Behat tests are much faster because they are run on an existing environment, where the site is not reinstalled for each test.

Concerning the PHPUnit tests, I used Functional tests to keep the test writing simple, with Kernel tests it would already have been much faster.

And we can see that the testCommentMailSend() test is much faster, for 2 reasons :

  • it doesn't make any requests to the Drupal front end, so there's no strain on the rendering layer
  • its prerequisites are much smaller, so when installing it for this test, there are fewer modules to activate and configurations to import.

Conclusion

These are 2 different tools that don't have the same advantages and disadvantages and can be complementary.

Depending, for example :

  • the project setup
  • the profile of the person in charge of testing
  • what there is to test
  • performance requirements

that's as many criteria for deciding to go for one or other of the tools, or both.

Comments

Add new comment