Using SimpleTest in Drupal 5

Submitted by Pawel on

I have been writing a unit test for the connect module using the simpleTest module. The following is a discussion of my experiences. This article from Lullabot is what I mainly used as a reference. Note that if you are following this article be sure to read the comments at the bottom. Especially that hook_simpletest is not required.

Installing SimpleTest

In Drupal 5 simpleTest uses a PHP library for its testing. In later versions of Drupal this library is not used. Once you have finished downloading the simpleTest module read the INSTALL.txt file. The only extra step to configuring this module is to download the simpleTest PHP library and placing it in the ...all/modules/simpletest/simpletest directory.

Writing a SimpleTest

Your tests go into tests directory inside your module. Inside this directory, place your tests into testname.test file (where testname is anything you want). Inside this file start by writing a class that extends DrupalTestCase.

class ConnectTest extends DrupalTestCase


After this write a get_info() function:


function get_info() {
    return array(
      'name' => t('Test for connect module'),
      'desc' => t('Does white box testing of the connect module'),
      'group' => t('Connect'),
    );
  }



This function lets simpleTest know what text to put in on the simpletest automation page. Once you have written this you can see the text show up in the list of tests (sight building->simpletest).



Now to the actual test. To write a test create a function inside your DrupalTestCase extension that starts with the word 'test'. All the functions that start with 'test' will be executed.



White-box testing is quite simple. White-box testing means that your test knows about the internal workings of your module. In simpler terms you can test all the internal functions of your module. Here is an example:



function testPostalCodeUtility() {
    $code = 'K1C 5E3';
    $returnVal = connect_is_postalcode($code);
    $this -> assertTrue($returnVal, t('connect_is_postalcode: valid postal code returns true'));    
    $code = 'KIC 5E3';
    $returnVal = connect_is_postalcode($code);
    $this -> assertFalse($returnVal, t('connect_is_postalcode: invalid postal code returns false'));
  }



You can see that connect_is_postalcode is being called. This is an function internal to the connect module. After this call I used assertTrue and assertFalse. Assertions will print out after you have run the test. Passes will show up in green and fails show up in red. Be sure to provide a good description of what is being tested to provide useful feedback to the user.


Black-box testing is a little more difficult. Black-box testing means that your test does not know the internal workings of the module. Instead of calling functions and testing the results you must browse the website as a normal user would and then use assertions that look for output to the screen. The first thing you need to do is to create a user:



//set up a user that can add a parent and child node
    $test_user = $this->drupalCreateUserRolePerm(array(
      'access administration menu',
      'access connect',	
      'create connect campaign',	
      'manage connect',
      'access content',
      'administer content types',
      'access administration pages',	
      'administer site configuration',
    ));
    $this->drupalLogInUser($test_user);

The main thing here is to get the users permissions correct. This was done so that you can test your module to make sure users without the correct permissions get handled correctly. But be sure that you have the permissions to be able to test what you want.


Now how do you navigate through the web page?


//create a parent node (campaign)
    $parent_node = array();
    $parent_node['name'] = $this ->randomName();
    $parent_node['type'] = strtolower($this ->randomName());  
    $this->drupalPostRequest('admin/content/types/add',$parent_node,'Save content type');
 



The main work done here is done by drupalPostRequest. The first argument it takes is the url that you are going to. This excludes your websites url all you put in is the stuff after q=. The second parameter is an array of values that you wish to post. The array should be indexed by the names of the inputs on the form (to find these look at the source code of the form). The last parameter is the name of the button to push for form input. This is simply the text you see on the button. This code creates a new content type. The additional function that is called is randomName. This function generates a random name that is prefixed with simpletest_. It is good to prefix things that you create with simpletest_ because sometimes they are left over in your database after you have run tests. Especially, in development, when there is an error in your test. A lot of things won't get cleaned up. It is easy to go into your database and see all the things that are left over because they will be prefixed by simpletest_. Note that there is a great button in simpleTest for drupal 6 that will automatically clean up your database after testing.



Finally you can call assertions that will look for a string on the current page of your internal browser:

$this->assertNoText('is required', 'Make sure no required fields are missing from edit campaign');

This code checks the current browser for the words 'is required'. In this case the assertion is used after posting a new node. If you missed a field that was required there will be a warning on the screen saying that the field is required.


Here are some additional code snippets that may be useful:


$node_campaign = node_load(array('title' => $add_campaign['title']));
$node_id = $node_campaign->nid;
</br>
You can load a node (as an object) and get its node id. <a href="http://api.drupal.org/api/function/node_load/5">Here is the api.</a>



$url = url('logout', array('absolute' => TRUE));
    $this->drupalGet($url);



This code is used to log out your user. This way you can log in with another user in the same test. The main reason to do this is if you want your new user to have different permissions. In my case I needed to do this because the new user needed to have permissions to create new node types created by the previous user.


Notes

When black-box testing it is difficult to see what exactly is going on. You can always print to the screen to check variables. But sometimes it is useful to put an exit before the end of your function. Your test will result in a white screen. But if you press the back button on your browser you will be able to see the user/content that you are setting up for your test. You can see what exactly your drupalPostRequest has set up (or has not set up). The annoying thing about this, sometimes this result happens when there is an error in the test, is that your database is littered with users/test input.

DrupalTestCase

The DrupalTestCase class is defined in drupal_test_case.php. This is the class that your test extend. The functions listed by this class is what you use to browse the page. Assertions are functions that you use to test values and display test results to the user. The following is a list of functions and assertions at your disposal, for more information look for comments in drupal_test_case.php:

  • function drupalCheckAuth($status = false)
  • function drupalGet($url)
  • function drupalRawPost($action, $edit = array())
  • function drupalPostRequest($path, $edit = array(), $submit)
  • function clickLink($label, $index = 0)
  • function drupalGetContent()
  • function randomName($number = 4, $prefix = 'simpletest_')
  • function drupalModuleEnable($name)
  • function drupalModuleDisable($name)
  • function drupalVariableSet($name, $value)
  • function drupalCreateRolePerm($permissions = NULL)
  • function drupalCreateUserRolePerm($permissions = NULL)
  • function drupalLoginUser($user = NULL, $submit = 'Log in')
  • function tearDown()
  • function run(&$reporter)
  • function assertWantedRaw($raw, $message = "%s")
  • function assertNoUnwantedRaw($raw, $message = "%s")
  • function assertNull($value, $message = "%s")
  • function assertNotNull($value, $message = "%s")
  • function assertIsA($object, $type, $message = "%s")
  • function assertNotA($object, $type, $message = "%s")
  • function assertEqual($first, $second, $message = "%s")
  • function assertNotEqual($first, $second, $message = "%s")
  • function assertIdentical($first, $second, $message = "%s")
  • function assertNotIdentical($first, $second, $message = "%s")
  • function assertReference(&$first, &$second, $message = "%s")
  • function assertCopy(&$first, &$second, $message = "%s")
  • function assertWantedPattern($pattern, $subject, $message = "%s")
  • function assertNoUnwantedPattern($pattern, $subject, $message = "%s")
  • function assertNoErrors($message = "%s")
  • function assertError($expected = false, $message = "%s")
  • function assertErrorPattern($pattern, $message = "%s")

Section: 

Code: 

Add new comment