1. 8.3.x core/core.api.php testing
  2. 8.0.x core/core.api.php testing
  3. 8.1.x core/core.api.php testing
  4. 8.2.x core/core.api.php testing
  5. 8.4.x core/core.api.php testing

Overview of PHPUnit tests and Simpletest tests.

The Drupal project has embraced a philosophy of using automated tests, consisting of both unit tests (which test the functionality of classes at a low level) and functional tests (which test the functionality of Drupal systems at a higher level, usually involving web output). The goal is to have test coverage for all or most of the components and features, and to run the automated tests before any code is changed or added, to make sure it doesn't break any existing functionality (regression testing).

In order to implement this philosophy, developers need to do the following:

  • When making a patch to fix a bug, make sure that the bug fix patch includes a test that fails without the code change and passes with the code change. This helps reviewers understand what the bug is, demonstrates that the code actually fixes the bug, and ensures the bug will not reappear due to later code changes.
  • When making a patch to implement a new feature, include new unit and/or functional tests in the patch. This serves to both demonstrate that the code actually works, and ensure that later changes do not break the new functionality.

Writing PHPUnit tests for classes

PHPUnit tests for classes are written using the industry-standard PHPUnit framework. Use a PHPUnit test to test functionality of a class if the Drupal environment (database, settings, etc.) and web browser are not needed for the test, or if the Drupal environment can be replaced by a "mock" object. To write a PHPUnit test:

  • Define a class that extends \Drupal\Tests\UnitTestCase.
  • The class name needs to end in the word Test.
  • The namespace must be a subspace/subdirectory of \Drupal\yourmodule\Tests, where yourmodule is your module's machine name.
  • The test class file must be named and placed under the yourmodule/tests/src/Unit directory, according to the PSR-4 standard.
  • Your test class needs a phpDoc comment block with a description and a @group annotation, which gives information about the test.
  • Add test cases by adding method names that start with 'test' and have no arguments, for example testYourTestCase(). Each one should test a logical subset of the functionality.

For more details, see:

Writing functional tests

Functional tests are written using a Drupal-specific framework that is, for historical reasons, known as "Simpletest". Use a Simpletest test to test the functionality of sub-system of Drupal, if the functionality depends on the Drupal database and settings, or to test the web output of Drupal. To write a Simpletest test:

  • For functional tests of the web output of Drupal, define a class that extends \Drupal\simpletest\WebTestBase, which contains an internal web browser and defines many helpful test assertion methods that you can use in your tests. You can specify modules to be enabled by defining a $modules member variable -- keep in mind that by default, WebTestBase uses a "testing" install profile, with a minimal set of modules enabled.
  • For functional tests that do not test web output, define a class that extends \Drupal\KernelTests\KernelTestBase. This class is much faster than WebTestBase, because instead of making a full install of Drupal, it uses an in-memory pseudo-installation (similar to what the installer and update scripts use). To use this test class, you will need to create the database tables you need and install needed modules manually.
  • The namespace must be a subspace/subdirectory of \Drupal\yourmodule\Tests, where yourmodule is your module's machine name.
  • The test class file must be named and placed under the yourmodule/src/Tests directory, according to the PSR-4 standard.
  • Your test class needs a phpDoc comment block with a description and a @group annotation, which gives information about the test.
  • You may also override the default setUp() method, which can set be used to set up content types and similar procedures.
  • In some cases, you may need to write a test module to support your test; put such modules under the yourmodule/tests/modules directory.
  • Add test cases by adding method names that start with 'test' and have no arguments, for example testYourTestCase(). Each one should test a logical subset of the functionality. Each method runs in a new, isolated test environment, so it can only rely on the setUp() method, not what has been set up by other test methods.

For more details, see:

Write functional PHP tests (phpunit)

Functional tests extend the BrowserTestBase base class, and use PHPUnit as their underlying framework. They use a simulated browser, in which the test can click links, visit URLs, post to forms, etc. To write a functional test:

  • Extend \Drupal\Tests\BrowserTestBase.
  • Place the test in the yourmodule/tests/src/Functional/ directory and use the \Drupal\Tests\yourmodule\Functional namespace.
  • Add a @group annotation. For example, if the test is for a Drupal 6 migration process, the group core uses is migrate_drupal_6. Use yourmodule as the group name if the test does not belong to another larger group.
  • You may also override the default setUp() method, which can be used to set up content types and similar procedures. Don't forget to call the parent method.
  • In some cases, you may need to write a test module to support your test; put such modules under the yourmodule/tests/modules directory.
  • Add test cases by adding method names that start with 'test' and have no arguments, for example testYourTestCase(). Each one should test a logical subset of the functionality. Each method runs in a new, isolated test environment, so it can only rely on the setUp() method, not what has been set up by other test methods.

For more details, see:

Write functional JavaScript tests (phpunit)

To write a functional test that relies on JavaScript:

  • Extend \Drupal\FunctionalJavaScriptTests\JavascriptTestBase.
  • Place the test into the yourmodule/tests/src/FunctionalJavascript/ directory and use the \Drupal\Tests\yourmodule\FunctionalJavascript namespace.
  • Add a @group annotation. Use yourmodule as the group name if the test does not belong to another larger group.
  • Set up PhantomJS; see http://phantomjs.org/download.html.
  • To run tests, see core/tests/README.md.
  • When clicking a link/button with Ajax behavior attached, keep in mind that the underlying browser might take time to deliver changes to the HTML. Use $this->assertSession()->assertWaitOnAjaxRequest() to wait for the Ajax request to finish.

For more details, see:

Running tests

You can run both Simpletest and PHPUnit tests by enabling the core Testing module (core/modules/simpletest). Once that module is enabled, tests can be run using the core/scripts/run-tests.sh script, using Drush, or from the Testing module user interface.

PHPUnit tests can also be run from the command line, using the PHPUnit framework. See https://www.drupal.org/node/2116263 for more information.

File

core/core.api.php, line 1038
Documentation landing page and topics, plus core library hooks.

Classes

Namesort descending Location Description
BrowserTestBase Deprecated core/modules/simpletest/src/BrowserTestBase.php Provides a test case for functional Drupal tests.
BrowserTestBase core/tests/Drupal/Tests/BrowserTestBase.php Provides a test case for functional Drupal tests.
KernelTestBase Deprecated core/modules/simpletest/src/KernelTestBase.php Base class for integration tests.
UnitTestCase core/tests/Drupal/Tests/UnitTestCase.php Provides a base class and helpers for Drupal unit tests.
WebTestBase core/modules/simpletest/src/WebTestBase.php Test case for typical Drupal tests.