Jul 11, 2014

Converting SimpleTest / Testing module classes for automated testing

The SimpleTest module became incorporated into Drupal 7 core as the Testing module. In Drupal 8 it retains its name of Testing. There have been a number of changes, some of which were made to follow conventions in D8.

As far as I can tell, the various flavors of assertions remain the same.

Here is the outline of a testing class for Drupal 8. I have omitted most of the actual code in order to focus on what is different. Explanatory notes follow the class definition.

File:  optimizely/src/Tests/OptimizelyAccessTest.php

namespace Drupal\optimizely\Tests;

use Drupal\simpletest\WebTestBase;

class OptimizelyAccessTest extends WebTestBase {

  protected $listingPage = 'admin/config/system/optimizely';
  protected $privilegedUser;
 
  public static $modules = array('optimizely', 'node');

  public static function getInfo() {
    // Same as before ...
  }

  public function setUp() {
   
    parent::setUp();

    $this->drupalCreateContentType(array(

      'type' => 'page', 'name' => 'Basic page'));
   
    $this->privilegedUser = 

      $this->drupalCreateUser(array(
        'access content',
        'create page content',
        'edit own page content',
        'administer optimizely'));

  }

  public function testUserWithPermission() {

    $this->drupalLogin($this->privilegedUser);
   
    $this->drupalGet($this->listingPage);
    $this->assertResponse('200',
      "User with 'administer optimizely' permission" .
      "
may access project listing page");
   
    $this->drupalLogout();

  }

}


Notes:

(1)  As a good organizing practice, create a separate folder for the test files. For example,
optimizely/src/Tests
The corresponding namespace declaration is then
namespace Drupal\optimizely\Tests;

(2)  Similar to other classes, each test class should be defined in its own file that has the same name as the class. For functional tests, the name of the test class must have the suffix "Test".


(3)  In D7 you declare the .test file in the .info file by using something like
files[]=optimizely.test
This is no longer necessary. The test files are auto-discovered by using the file and class naming conventions.


(4)  The core module class DrupalWebTestCase has been renamed to WebTestBase. The use statement so that that class can be referred to by its unqualified name is
use Drupal\simpletest\WebTestBase;
The other core base classes are UnitTestBase and DrupalUnitTestBase.


(5)  Instead of the following call in the setup() method of the test class
parent::setUp('optimizely');
add a declaration of $modules like the following to the test class definition in order to enable the module you're testing. Also, call the parent setup() method with no arguments in order to do other parental setup.
public static $modules = array('optimizely');

parent::setUp();

(6)  By default, testing is done using a low-weight testing profile. However, for example, if you need permissions that are defined by core modules such as node, the testing profile does not provide them. You will get an Invalid permission error.

One way to solve this is to use the standard profile by adding the $profile property to the test class.
protected $profile = 'standard';
Use of this profile provides an easy blanket solution, but some comments claim it may cause tests to run noticeably slower. Another approach is to explicitly enable those core modules that are needed, like this for the node module.
public static $modules = array('optimizely', 'node');
However, enabling the core module may not be enough. For example, I found that to be able to use permission create page content I also had to create the content type.
$this->drupalCreateContentType(array(
  'type' => 'page', 'name' => 'Basic page'));

(7)  If you have the xDebug extension enabled for PHP, disabling the extension will speed up the running of tests. I have reduced some test run times by almost half by disabling xDebug.


Update: see  http://optimizely-to-drupal-8.blogspot.com/2014/12/beta-3-beta-4-configuration-schema-and.html


Sources:

Converting D7 SimpleTests to Drupal 8
https://www.drupal.org/node/2166895

Drupal SimpleTest coding standards

https://www.drupal.org/node/325974

Namespace and naming changes for test classes of automated tests
https://www.drupal.org/node/1543796

New simpletest class property $modules to enable modules in tests instead of WebTestBase::setUp($modules)
https://www.drupal.org/node/1710766

Simpletest automated tests now use empty 'testing' profile by default
https://www.drupal.org/node/1911318

2 comments:

  1. Disabling xDeug could be a pain considering you're running tests that might lead to the need to use your IDE. Toggling xDeug on and off sounds like a pain and potential source of confusion.

    ReplyDelete
  2. Yes, it would be a pain if I had to toggle xDebug off / on a lot. For now, I keep it disabled since I haven't needed the debugger yet. The logic for the tests has been straightforward so far. That may change with the more complex test scenarios.

    ReplyDelete