Blog/ 15 minutes to your first Drupal integration test

This post will help you write and run your first Drupal integration test using Red Test framework in less than 15 minutes. By end of this post, you will be able to write an automated test to make sure that superuser is able to create two pieces of content, one published and the other unpublished. We'll test that anonymous user is able to view the published content and is not able to view the unpublished content. You can follow along these steps on any Unix or Mac machine and have automated tests running in a matter of minutes.

1) Choose any Drupal 7 site that you have running on your machine.

2) Go through the Red Test installation post and install Red Test in this site. You can skip the last step in this post where we run the tests since the test suite that comes by default is the one meant for Standard installation profile of Drupal and will invariably fail with your custom site.

3) Create a new content type called "Test Me". Note that machine name of the content type should be "test_me". This is important because Red Test identifies content based on its machine name and not its label.

4) Remove the body field from the "Test Me" content type and add a new field: "Test Me Body" (machine name: field_test_me_body). It should be a "Long Textarea With Summary" field.

5) First we need to inform Red Test about the "Test Me" content type. Go to <DRUPAL_ROOT>/tests/folder/RedTest/entities/Node folder.

cd <DRUPAL_ROOT>/tests/RedTest/entities/Node

Create a new PHP file named TestMe.php. Create a class called TestMe which extends Node class.

8) Create a file named AnonymousUserTest.php. This is the file where we'll be writing our test. Red Test is based on PHPUnit so if you know PHPUnit, this will be extremely easy for you. Create a class named AnonymousUserTest that extends RedTest_Framework_TestCase. In the setupBeforeClass() method, we'll log in as Superuser (uid = 1) and create two pieces of content of the type "Test Me", one published and the other unpublished. Then we'll test the following:

Anonymous user has access to view the published content.

Published content that the anonymous user sees has "field_test_me_body" in it when viewing in "full" view mode.

Anonymous user does not have access to view the unpublished content.

Below is the code which tests the above scenarios. The code is well-commented so it should be easy to understand what's going on.

<?php
namespace RedTest\tests\entities\node\test_me\crud;
use RedTest\core\entities\User;
use RedTest\core\RedTest_Framework_TestCase;
use RedTest\entities\Node\TestMe;
use RedTest\core\Menu;
use RedTest\core\Path;
/**
* Class AnonymousUserTest
*
* @package RedTest\tests\entities\node\test_me\crud
*/
class AnonymousUserTest extends RedTest_Framework_TestCase {
/**
* @var TestMe
*/
private static $publishedTestMeContent;
/**
* @var TestMe
*/
private static $unpublishedTestMeContent;
/**
* Create a published and an unpublished content of the type
* "Test Me".
*/
public static function setupBeforeClass() {
$options = array(
'required_fields_only' => FALSE,
'status' => 'published',
);
// Log out the user just to make sure that there is no
// logged in user at this point.
User::logout();
// Log in as user 1.
$userObject = User::loginProgrammatically(1)
->verify(get_class());
// Create a published TestMe content with all its fields
// filled with random values.
self::$publishedTestMeContent =
TestMe::createRandom(1, $options)->verify(get_class());
// Create an unpublished TestMe content with all its
// fields filled with random values.
$options['status'] = 'unpublished';
self::$unpublishedTestMeContent =
TestMe::createRandom(1, $options)->verify(get_class());
// Log the user out. After this step, the user will be
// anonymous.
$userObject->logout();
}
/**
* Make sure that anonymous user has access to view the
* published "Test Me" content.
*/
public function testPublishedViewAccess() {
// Use node_access() function to check whether user has
// access to view the published content.
$access = self::$publishedTestMeContent->hasViewAccess();
$this->assertTrue($access,
'Anonymous user does not have permission to view a
published "Test Me" content.');
// Use Menu class' hasAccess() function to check whether
// user has access to node/<nid> page. This is a more
// general function and can be used for custom paths as
// well.
$id = self::$publishedTestMeContent->getId();
$path = new Path('node/' . $id);
$access = $path->hasAccess();
$this->assertTrue($access,
'Anonymous user does not have permission to view a
published "Test Me" content.');
}
/**
* Make sure that anonymous user is able to view the
* published "Test Me" content in "full" and "teaser" view
* modes.
*/
public function testPublishedView() {
// Get the renderable array of the node in "full" view
// mode. Note that a node in "full" view mode does not
// have title inside it. The title is being rendered by
// page tpl.
$view = self::$publishedTestMeContent->view('full');
$this->assertArrayHasKey('field_test_me_body', $view,
'Anonymous user is not able to view the body field of
the published content in "full" view mode.');
}
/**
* Make sure that anonymous user does not have access to
* view the published "Test Me" content.
*/
public function testUnpublishedViewAccess() {
// Use node_access() function to check whether user has
// access to view the unpublished content.
$access =
self::$unpublishedTestMeContent->hasViewAccess();
$this->assertFalse($access,
'Anonymous user has permission to view an unpublished
"Test Me" content.');
// Use Menu class' hasAccess() function to check whether
// user has access to node/<nid> page. This is a more
// general function and can be used for custom paths as
// well.
$id = self::$unpublishedTestMeContent->getId();
$path = new Path('node/' . $id);
$access = $path->hasAccess();
$this->assertFalse($access,
'Anonymous user has permission to view an unpublished
"Test Me" content.');
}
}

9) Now that we have the test set up, we want to inform Red Test that this is the test that needs to be run and not any other test that comes by default. Open <DRUPAL_ROOT>/tests/phpunit.xml file and in the directory tag under testsuite, write "./RedTest/tests/entities/node/test_me". Here is how the phpunit.xml file will look:

You will notice that the test completed in less than a second, more specifically in 780 ms. The same test would have taken a few seconds to run using Simpletest or Behat. Although a few seconds don't seem like much, it quickly adds up. Also Red Test is designed to run multiple scenarios in parallel and it doesn't bootstrap Drupal for each test separately. Currently we have just one test. So the speed-up by using Red Test will be even more when we add more tests.

If you did go through the example on your system and got stuck somewhere, please write it in the comment with your email id or email me at [email protected]. I can help you with the setup. If the tests passed, then write a comment and note down how much time it took to run the test!

Sir, Actually In My custom module, I rendered a node form of existing content type in menu callback. I just want to test when I hit that URL then I get particular that node form. After that I want to submit this form with custom value. How will I achieve this in Red test cases.

In simple test case, I successfully tested it but execute of this test case is quite time consuming.

Sir, Actually In My custom module, I rendered a node form of existing content type in menu callback. I just want to test when I hit that URL then I get particular that node form. After that I want to submit this form with custom value. How will I achieve this in Red test cases.

In simple test case, I successfully tested it but execute of this test case is quite time consuming.