Converting D7 SimpleTests to Drupal 8

Last updated on
3 April 2017

Some notes on converting Drupal 7 SimpleTest-based tests to Drupal 8.

Directories and Namespaces

In Drupal 7, SimpleTest-based tests are in the modulename.test file. This file is expected to contain all test classes. There are no unique namespaces.

Drupal 8 uses namespaced classes, in named subdirectories, to organize code and enable PSR-4 autoloading. For a contrib module modulename, this means:

  • SimpleTest tests should be in the namespace Drupal\modulename\Tests\ and the module subfolder src/Tests/.
  • PHPUnit tests, not otherwise discussed here, should be in the namespace Drupal\Tests\modulename\ and module subfolders tests/src/Unit, tests/src/Functional, or tests/src/Kernel.

For SimpleTest tests, then:

  1. Create a subfolder in your module: src/Tests.
  2. Move your modulename.test file into this subfolder. This is for convenience's sake as you refactor the test classes out of this file.
  3. Separate out all of the test classes from modulename.test:
    • If your modulename.test file has three test classes in it, you'll end up with three files, one per class.
    • Each separate file should be named based on a class it contains: for example, if your test class name is MymoduleLoginTest, the filename should be MymoduleLoginTest.php.
    • It's often easier to fully convert one class first, then you have a template for subsequent ones.
  4. Give your stub classes their own namespace, and move them into a deeper subfolder. Your tests' namespace is \Drupal\modulename\Tests, and your stubs' namespace should be something like \Drupal\modulename\Tests\Stub.
  5. Mock modules can go in tests/modules. The subfolder tests/; ought to be where PHPUnit-based tests go, but as yet there is no convention about where to place mock modules for SimpleTest.

Convert the code

Commenting: The first thing to keep in mind is that this is an excellent opportunity to finish all those docblock and inline comments you always thought you'd get around to, but never did. Go on... It's not that hard. Drupal.org comment doc standards here: https://drupal.org/coding-standards/docs

Drupal Coding Standards: Drupal.org has a SimpleTest coding standards document here: https://drupal.org/node/325974 You should probably adopt these standards, even if you're not a core developer.

Class Names: SimpleTest searches for tests by finding files that end in Test.php. This means your test class files should end in Test.php, which also means your test class names should end in Test. Clear? :-) If your Drupal 7 testing class has a name like ThisIsATestCase then you'll need to change it to ThisIsATestCaseTest for Drupal 8. And you should put it in a file named ThisIsATestCaseTest.php so that SimpleTest can find it.

Base Classes: The names of the base classes have changed.

  • DrupalWebTestCase is now Drupal\simpletest\WebTestBase
  • DrupalUnitTestCase is now Drupal\simpletest\TestBase

Convert to PHPUnit: Note that Drupal 8 also has included PHPUnit, which you should use for disciplined unit testing. This is in contrast to TestBase, which still initializes Drupal, but does not connect to the database. Where possible, convert unit tests to PHPUnit. Drupal PHPUnit documentation here: https://drupal.org/node/2116239

Dependencies: One of the more important things is that, in WebTestBase, module dependencies don't live in setUp() any more. You'll need to add a static property to your test class called $modules, which will be an array of module names:


// Drupal 7: public function setUp() { parent::setUp('some_module', 'some_other_module'); } // Drupal 8: public static $modules = array('some_module', 'some_other_module'); 

getInfo(): The method getInfo() should give some metadata for the test in Drupal 7. In Drupal 8 this data should be put in PHPDoc comments. The name will be taken from the class name, and the description, group and dependencies info will be read from the PHPDoc comment for the class. See Test class getInfo() method removed in favor of PHPDoc for full instructions.

drupalPost() and drupalPostForm(): In order to accommodate a distinction between an HTTP POST request and a form submission to Drupal, WebTestBase now has these two methods. Formerly, drupalPost() handled both, but now it performs a POST request. drupalPostForm() has the same calling signature as the old drupalPost(), so it's an easy conversion. Change notice here: https://drupal.org/node/2087433