Writing Automated Tests in Drupal

Automated tests are an essential part of ensuring the code we write is reliable, that future updates don’t cause regressions, and that our applications remain stable.

This course covers the creation and configuration of PHPUnit for testing, how to implement unit, kernel, and functional tests, and writing tests that run in a simulated browser.. Additionally, learners will explore JavaScript testing using tools like Nightwatch.js, and understand how to manage test dependencies effectively. By the end of the course, you will be able to write automated tests that ensure your Drupal code is reliable, maintainable, and free of regressions.

Key topics

  • Customizing PHPUnit configuration for your Drupal project
  • Write and run functional tests, kernel tests, and unit tests
  • Explicitly declare and manage a test's dependencies (e.g. what modules are enabled?)
  • Functional JavaScript tests and related tools like WebDriver and Nightwatch.js
  • Converting old Simpletest tests to PHPUnit
  • Best practices for organizing test files within your project
  • Techniques for debugging failing tests, including using tools like PhpStorm, DDEV, and xDebug
Tutorials in this course
More information

When running tests with PHPUnit we need to specify a phpunit.xml file that contains the configuration that we want to use. Often times (and in much of the existing documentation) the recommendation is to copy the core/phpunit.xml.dist file to core/phpunit.xml and make your changes there. And this works fine, until something like a composer install or composer update ends up deleting your modified file. Instead, you should copy the file to a different location in your project and commit it to your version control repository.

In this tutorial we'll:

  • Learn how to move, and modify, the phpunit.xml.dist file provided by Drupal core
  • Understand the benefits of doing so
  • Demonstrate how to run phpunit with an alternative configuration file

By the end of this tutorial you should be able to commit your phpunit.xml configuration file to your project's Git repository and ensure it doesn't get accidentally deleted.

Categories
Drupal 8, 9, and 10
More information

In this tutorial, we'll walk through the process of setting up a functional test. Then, we'll learn how to run it using two different test runners. This setup process allows us to be sure we're not getting false positives from the test runners. We'll be working on a functional test, but these techniques apply with minimum modification to all the Drupal PHPUnit-based tests.

By the end of this tutorial, you should be able to set up and run functional tests in Drupal using two different test runners.

Categories
Drupal 8, 9, and 10
More information

In this tutorial, we'll walk through the basics of how to implement a functional test by extending Drupal's BrowserTestBase class. We'll assume you've already determined that you need to write a functional test and that you've Set up a Functional Test.

In this tutorial, we'll:

  • Determine the specifications of the test.
  • Walk through the behavior we want to test.
  • Document our test in the test class.
  • Implement the testing steps.
  • Decide how to deal with dependencies (for now). (We'll go into details about handling test dependencies in Implement Drupal Functional Test Dependencies.)
More information

Previously, in Implement a Functional Test, we learned how to tell BrowserTestBase to use the Standard installation profile in order to get our test passing, letting the Standard profile implicitly provide our dependencies. We mentioned that doing so probably wasn't the best decision and that we should explicitly declare those dependencies instead.

In this tutorial, we'll walk through how to explicitly declare our test's dependencies. When in doubt, it's generally considered a best practice to be as explicit about the dependencies of our tests as possible. By the end of this tutorial, you should be able to:

  • Understand why we want to explicitly declare our dependencies.
  • Determine what the dependencies really are and make a list of them.
  • Implement each dependency in our list.
  • Emerge with a thorough passing test.
More information

Let's write somewhat strict unit tests in a Drupal module. By the end of this tutorial, you will be able to:

  • Understand what makes a unit test different from other types of tests.
  • Determine the specifications of a unit test.
  • Use mocking to isolate units under test, and to force code flow to achieve high coverage.

We'll start out with a brief introduction to unit tests. Then we'll look at a contrived example of a Drupal controller class for illustration purposes. Next, we'll test two units of this controller class, each requiring different mock styles.

Categories
Drupal 8, 9, and 10
More information

In order to execute functional tests that require JavaScript be executed for the feature to work the tests need to be run in a browser that supports JavaScript. This is accomplished by using the WebDriver API in combination with an application like ChromeDriver or Selenium which can remotely control a browser.

The exact setup for running functional tests is dependent on your development environment. We'll walk through a couple of common examples including using Docker (via DDEV) and stand-alone applications.

In this tutorial we'll:

  • Learn how to install and run ChromeDriver and other necessary tools either in a Docker environment, or locally.
  • Configure the relevant PHPUnit environment variables so they contain values appropriate for our specific environment.
  • Execute Drupal's functional JavaScript tests via the phpunit command.

By the end of this tutorial you should be able to install the applications required to run functional JavaScript tests in a browser, and know how to configure PHPUnit to make use of them.

More information

The testing suite for the Drupalize.Me site uses a different strategy for functional JavaScript testing. We use a tool called Nightwatch.js that allows us to write our tests in JavaScript that runs commands against a web browser. This browser automation allows us to test the types of interactions that a typical user of our website might encounter. It also allows us to test JavaScript code using JavaScript, and execute our tests in different browsers. In this tutorial we'll take a look at how to set up Nightwatch.js, and what the syntax looks like for a couple of basic tests.

More information

Simpletest has been removed from Drupal 9. If you're preparing to upgrade your site to the latest version of Drupal and you have Simpletests in your codebase that extend WebTestBase you'll need to update them to use PHPUnit's BrowserTestBase class instead. This will ensure your tests don't depend on a deprecated testing framework. By the end of this tutorial, you should be able to convert WebTestBase-based Simpletests to use PHPUnit's BrowserTestBase class instead.

This course appears in the following guides:
Module Development
Learn how to run and write unit, kernel, and functional tests for your custom Drupal code.

Test Custom Code