This project is not covered by Drupal’s security advisory policy.

TestData is a developer module intended for large Drupal sites that require a consistent, fast method of providing sample data to automated acceptance and performance testing tools.

The Grinder, jMeter and Selenium are examples of tools that test your site by creating real traffic that mimics user actions. Writing these tests often requires easy access to your site's data, for usage in the tests.

Use case: hard-coded vs dynamic data

An example test case may be: go to an article, post a comment, assert that the comment appears. In writing this script, you'll quickly discover you either have to hard-code the URL of an article in the test, or write extra steps to find an article (e.g. go to the homepage, search for a link to a /node/xxx, click that). This can result in your test scripts becoming fragile and slow. Hard-coding a link results in a test that only ever runs against a single item - this is especially problematic in load testing.

TestData usage

The TestData module provides external access to the data you need. For example, you could write the following hook to provide a test data set:

/**
  * Implementation of hook_testdata_sets().
  */
function mytestdata_testdata_sets() {
  return array(
    'random-article' => array(
      'query' => "SELECT nid as item
                  FROM {node}
                  WHERE type = 'article'
                  AND status = 1
                  ORDER BY RAND()",
      'description' => 'A random published article',
      'size' => 2000,
      'url_format' => 'node/%',
    ),
  );
}
'random-article'
The unique key of the test data set, used for requesting data and caching
'query'
The potentially expensive query to be executed to populate the data set
'description'
A brief description of what the data set provides
'size'
The maximum amount of data to query from the database
'url_format'
The '%' is substituted for each data item to turn them into URLs, e.g. 'node/x', 'node/y'

The following URLs are automatically provided:

URLs provided by TestData

/testdata/goto-next/random-article
Redirect to the next url in the set 'random-article' using drupal_goto()
/testdata/get-json/random-article/X
Return JSON data structure containing the next X items from the 'random-article' set
/testdata/get-urls-json/random-article/X
Return JSON data structure containing the next X items formatted as URLs (node/X) from the 'random-article' set

In PHPUnit Selenium, we can then execute:

// Go to the next random article in the set. 
$this->open('testdata/goto-next/random-article');

Under the hood

TestData turns each dataset into a cached looping iterator. It will execute your query only once, and cache the results with the current position using the provided key. Each time you hit /testdata/goto-next/x, $x->next() is called on the iterator, it returns the next item and increments the current position. At the end of the page request, the current position is saved back to the cache so that the next time testdata/goto-next is requested, a new item is returned.

This mechanism has the following benefits:

  • Execute expensive queries only once, instead of on each page load.
  • Create a very large random dataset initially, possibly encompassing all data, and move sequentially through it, instead of picking a random item on each hit. Provides better coverage of test data.
  • Multiple simultaneous test worker threads can each get a different portion of a large random set of test data, so that they don't all move through the same data list in the same order. This is very useful for load testing, for example, where you don't want multiple threads all hitting the same list in the same order, as caching could potentially negate the point of having multiple threads. You want them all to hit a different item. This potentially requires a small ramp-up period.
  • Loops back to the beginning when it runs out of data, so tests don't need logic for handling the end of list.

This module was sponsored by The Economist Online.

Project information

Releases