Drupal SimpleTest coding standards

Last updated on
29 January 2017

You should follow these conventions when writing a test.

Naming conventions

Drupal 8

namespace Drupal\$module\Tests;

use Drupal\simpletest\[Web|Unit|Kernel]TestBase;

Foo[Unit]Test extends [Web|Unit|Kernel]TestBase

The class name should end in "UnitTest" if it's a unit test (Unit or Kernel), and just "Test" if it's a web-based test.

File names Drupal 8

Drupal 8 supports PSR-4, so the path should be:
For more information, see PSR-4 namespaces and autoloading in Drupal 8

Drupal 6/7

Foo[Unit]Test extends [Web|Unit]TestCase

File names Drupal 6/7

  • For modules, a single [modulename].test file is the general rule. It should be placed directly in the module folder.
  • For core facilities (all API functions that are in includes/), tests files are named [facility name].test and are placed in the modules/system/tests folder.
  • If other supporting files are required for the tests to work (for example, hidden modules, XML files, images) they should be located in a /tests/ subdirectory within the module directory.

Mock module names Drupal 6/7/8

  • If a test requires defining hooks, it can create a mock module.
  • This module should be named [test file name]_test.module (its associated info file would then be [test file name]_test.info.
  • Set the property hidden = TRUE in the .info file to prevent it from being enabled in the interface.

Test function names

All tests functions are prefixed with test.

Splitting up your tests

When you're unit testing a single function--as opposed to doing functional testing of a module's page--each test function should focus on a specific aspect of the function's operation. The "kitchen sink" style of tests is common in core right now but it's bad practice. Test should serve two purposes:

  • Ensure that the code operates in a certain way
  • Provide a runnable example of the code's usage

Monolithic tests generally fail badly because once one portion of the tests fails, it cascades through the later tests. This makes it hard to isolate exactly where the fault lies. By breaking the code up into separate tests you may duplicate some code--though if you're duplicating code between a majority of the tests it should probably go into the setUp() function--but you'll have an isolated test that passes or fails on its own.

You also get several positive side effects by writing smaller tests:

  • Each test becomes a simple, self-contained example of how the function can be used, answering the question "Given these inputs what behavior can I expect?"
  • Since each test only looks at a single aspect you'll find that you're much more willing to test edge cases. Unlike kitchen sink test you won't have to worry about "breaking up the flow" with an extra test.

Test template

After the opening PHP tag and a blank line comes the @file declaration:

 * @file
 * Contains \Full\Namespace\Of\The\TestClassName.

If there is no namespace (Drupal 7 and previous), omit that.

The next thing in the file is the class declaration:

 * Tests kitten basket functionality.
class KittenBasketTestCase extends DrupalWebTestBase {

The comment above, the class is mandatory, and it should start with a verb and generally follow our class documentation standards:
It should be a rephrasing of the 'name' of the test found in getInfo() function ('Kitten basket functionality' -> 'Tests kitten basket functionality').

There are several special methods on test classes:

   * {@inheritdoc}
  public static function getInfo() {
    return array(
      'name' => 'Kitten basket functionality',
      'description' => 'Move kittens in and out of their basket and assert that none of them were hurt in the process.',
      'group' => 'Kitten basket',
  • The very first function has to be getInfo().
  • name, description and group are not enclosed in t() calls.
  • name should be short and should not contain any period. It should describe an overview of what subsystem is tested by the class; for example, "User access rules" or "Menu link creation/deletion"
  • description should start with a verb describing the test. It should end with a period.
  • group should be the human-readable name of the module (Node, Statistics), or the human-readable name of the Drupal facility tested (Form API or XML-RPC).
   * {@inheritdoc}
  public function setUp() {
    parent::setUp('kitten_module', 'basket_module');
     // Setup tasks go here.
  • setUp() is optional. If your test is for specific module(s), make sure to pass each module's name as a parameter to setUp() so it will be automatically enabled for you. If the module doesn't have to perform any particular setup, it should not be defined.
  • Drupal 8: to enable specific modules, calling setUp()with their names as arguments is no longer used. See New simpletest class property $modules to enable modules in tests instead of WebTestBase::setUp($modules)
  • setUp() and tearDown() are called before and after every test function is called.
   * {@inheritdoc}
  public function tearDown() {
    // Teardown tasks go here.
  • tearDown() should not be used, except in very particular cases. Simpletest will simply drop the test database, so you don't even have to undo the setup tasks performed in setUp().
  • setUp() and tearDown() are called before and after every test function is called.

Remaining methods whose names start with "test" are individual tests that will be run, such as:

   * Tests example thing.
  public function testExampleThing() {
    // Assertions, etc. go here.

   * Tests next example thing does the thing correctly.
  public function testNextExampleThing() {
    // Assertions, etc. go here.
  // Can have many more testFoo functions.