Drupal 7 module integration testing
The information below is available in other places, but I figured I would bring it together as a sort of note-to-self, because this had me stumped for a day.
Suppose you have a Drupal contrib module A that you are writing tests for.
Contrib module B is optionally extending the functionality of module A, and you want to test the integration of these two modules.
Drupal has tons of modules that either are built specifically to extend the functionality of another module, or that are built as some sort of low-level API module that lets you do cooler stuff with the functionality you already have. For example, the Feeds module is optionally extended by Feeds Tamper, Feeds Import Preview, Feeds Entity Processor and so on.
So let us say that somewhere in your code for module A you have the following:
if (function_exists('module_b_api_function')) {
// Do cool stuff with module_b_api_function().
}
Now in order for your test runner to call this function, you need to tell it about the existence of the dependent module. It needs to be able to activate the module or to fail gracefully if it cannot (for instance if the second module does not exist).
The following assumes you are acquainted with the Drupal 7 built-in testing system (Simpletest), specifically with the DrupalWebTestCase.
There are three places where you define the integrated module you want to load: your module’s .info file and in the the setUp() and getInfo() methods of the .test file for your integration test.
1. In your module’s .info file, add:
test_dependencies[] = module_b
(where ‘module_b’ should be replaced by the name of the module that provides the extended functionality).
This alerts the drupal.org test runner that it needs to add module B to its code base.
1.b. If you are patching an existing contrib module, you may wish to create a separate patch of just this change first, because the drupal.org test runner needs to know about your test_dependency before it starts running the actual integration test patch.
Update 20 August 2019: this preliminary patch must be committed to the module’s development branch by the module’s maintainer. This is something that at first completely flew by me, because all of the documentation on this particular test runner quirk was written by module maintainers, and when they write ‘commit’, it means something else than when I read ‘commit’—in my mind, committing refers to my local repository. Yeah, I know…
2. Your setUp() method might look like this:
public function setUp(array $modules = array()) {
$modules[] = 'module_b';
parent::setUp($modules);
}
This enables the modules during the test run.
3. Your getInfo() might look like this:
public static function getInfo() {
return array(
'name' => 'Module B integration tests',
'description' => 'Test integration with the B module.',
'group' => 'module_a_group',
'dependencies' => array('module_b'),
);
}
The Simpletest uses the return value amongst others to check (in simpletest_test_get_all()) that the modules the test depends on, are discoverable. If they are not, your module integration test is skipped.
If you leave out this third step, the testing system will halt with a fairly useless error message upon discovering it cannot load the module. That is OK for you, now that you know what is happening, but not for others who might never have seen your tests and are just seeing their own test runs fail. Having your test skipped in case of a missing module is nicer.
Leave a Reply