samedi 3 novembre 2012

Drupal Functional Testing tips and tricks

I am writing this article to help people not making the same mistakes as me when using Drupal SimpleTest in any serious website/application developpement.

The first very thing you have to understand about the architecture is that in Web Test Cases (not Unit ones), there is two sites under test: the site who trigger the tests and displays the results, and the site accessed by the internal browser.

Replacing drupal_static with mocked/stub class

This can be a little tricky to understand when you need to mock/stub some static defined variables. For instance, in the module I am developping in my free time (World of Wacraft API) I am mocking a class representing the Service API of Blizzard to redirect HTTP calls to my file system where resides test material such as .json files.

The pattern I am using to get an instance of this service class is a Service Locator, in my tests I should just replace the drupal_static('wow_service') object with my mock, but it does not work like that.

Remember that when you set this in the setUp() class, e.g. doing that:

function setUp() {
  $services = &drupal_static('wow_service');
  $services['eu'] = new ServiceStub('', array('fr' => 'fr_FR'));
}

will set the static registry for the site running the tests, not the Site Under Test (SUT) that you assert functional tests with the internal browser.

To set the variable in the SUT, you'll have to use a trick: creates an empty module that will configure your site under test with the service stub. By creating a module wow_test.module; enabling it in the setUp() method, will allow the code to be run in the context you want, and no longer in the site running the tests suit.

In wow_test.module, I implements the hook_init() and copy my two lines of code to initialize correctly the service stub.

function wow_test_init() {
  $services = &drupal_static('wow_service');
  $services['eu'] = new ServiceStub('', array('fr' => 'fr_FR'));
}