Like many open-source projects, Drupal comes with automated tests that help prevent breaking changes while promoting code quality. Drupal 8 has changed its testing framework for unit and functional tests from its own Simpletest framework to PHPUnit, following Drupal 8’s strategy of using more third-party libraries in core. All Simpletests have been moved to PHPUnit as of Drupal 8.7.x.
PHPUnit can handle different types of tests in Drupal core: unit tests, kernel tests, and functional tests. With these three tests, you can confirm the quality and reaction of code on edge cases in different layers.
Your unit tests won’t be found unless they follow specific file structure, namespace, and metadata requirements. Drupal Console can generate a stub test when generating a module.
Unit test mocks are created using Prophecy.
Per the documentation of the KernelTestBase class, kernel tests are “useful for testing some types of integrations which don’t require the overhead of a fully-installed Drupal instance, but which have many dependencies on parts of Drupal which can’t or shouldn’t be mocked.” The class partially boots Drupal, and can load the services and hooks of other modules. The documentation says that the configuration, database schema, and entity schema could be installed for some modules, but it’s not clear which modules support this.
PHPUnit browser functional tests are run against a fresh Drupal installation so each test requires set up like installing modules, creating users, etc. This can be done in the BrowserTestBase::setUp() method (which is run before each test method in the class) or by writing an abstract base class (that extends BrowserTestBase) to be extended by additional test classes. You could also simply run a previous test at the beginning of the test you are writing. The results of the browser tests are saved to a directory, which can be configured in the phpunit.xml file. See PHPUnit Browser test tutorial in the Drupal documentation.
While not part of Drupal core, some contributed modules also include tests using the Behat framework. Behat uses the Gherkin syntax to describe features, which are then translated to functional and UI tests.
Behat tests would be used to test site-specific functionality and uses the site’s database, rather than a clean installation of Drupal. The Behat Drupal Extension is an open-source project that provides drivers and useful step definitions for Drupal. Tests are organized into features, scenarios, and steps. Features and scenarios can be tagged to be run in groups, or to let Behat know to use a certain driver.
While this Gist offers a helpful list of step definitions provided by the Behat Drupal Extension, users can also run the command “behat -dl” for a list of steps defined for a system.
Each of these steps uses a different driver, which provides a different layer of integration with Drupal.
The Drush driver uses the Drush command line tool to complete steps. In order to use the Drush driver, the feature or scenario must be tagged with @api. The Drush driver allows tests to use all the blackbox steps, plus a few more steps like logging in and creating users. The Drush driver can be run on multiple sites via Drush aliases.
Drupal API Driver
The Drupal API driver provides more complex steps, but can only be run on one site at a time. Behat can be configured to use this driver when features or scenarios are tagged with @api. Behat can be configured to run either the Drush driver OR the API driver at one time.
Custom Step Definitions
Custom step definitions would be added to the FeatureContext.php file that gets created when Behat is initialized for a project. The step text and any arguments are set up in annotations to functions in the FeatureContext class. See the Behat documentation for details.
Unit and functional tests are a great way to help improve your code quality. Drupal core supports many different kinds of tests that focus on different parts of the system, and some tests may be better for testing different things. Look for a future blog post on how to run these tests, and incorporate automated testing into your workflow.