Blog/ Testing blocks using Red Test

By neerav.mehta Thu, 06/18/2015 - 02:00 Comments

Have you ever worked on a large project where out of the blue, one day, the client says that editors are not seeing a block of new blog posts in right sidebar on so and so page? It's generally pretty easy to fix this problem. Just go to the configuration form of that block and see what the conditions are for displaying the block. Or it could be a block written by you in a custom module and then you'll need to check hook_block_view() in your module to see where the problem lies. But you are still unhappy because the bug was caught on production. Have you thought of automating the block test so that a block with wrong settings never gets deployed in production? In this post, we'll show you how to automate the test for blocks in less than 10 mins. You can following these steps on any Unix or Mac machine.

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) Now let's create a block that needs to be tested. Go to /admin/structure/block/add and create a new custom block. Write block title as "Homepage block". Write description as "Block only visible on homepage". In block body, write "Block body".

4) Now let's add the Region and Visibility settings to this block. Go down the page. Under "Region settings", add the block to "Sidebar first" region. Under "Visibilty settings", click on "Pages". The click on "Only the listed pages" and in the textbox below, write "<front>".

5) Save the form. Now this block will be visible in sidebar first region only on the homepage. Once saved, you will be taken back /admin/structure/block page and you will be able to see your shiny new block in Sidebar first region. You need the block id for testing later since that's how Drupal remembers it internally. Just hover over the "configure" link of that block and the second to last argument in the path will be the id. In our case, the block id is "1".

5) Now let's create a test for it. Once you have installed the Red Test framework, change directory into <DRUPAL_ROOT>/tests/RedTest/tests folder. It has an existing folder called "blocks". It comes with tests for the blocks that pass on Drupal's standard installation profile. We don't need it anymore so delete it and create a new "blocks" directory and change into that directory.

cd <DRUPAL_ROOT>/tests/RedTest/tests
rm -rf blocks
mkdir blocks
cd blocks

6) Create a file named "AnonymousUserTest.php". Paste the following test in it.

<?php

namespace RedTest\tests\blocks;

use RedTest\core\Block;
use RedTest\core\entities\User;
use RedTest\core\RedTest_Framework_TestCase;


/**
 * Class AnonymousUserTest
 *
 * @package RedTest\tests\blocks
 */
class AnonymousUserTest extends RedTest_Framework_TestCase {

  /**
   * Make sure that homepage block is present on homepage and not on
   * /user/login page. Also make sure that block title and body are as 
   * expected.
   */
  public function testHomepageBlock() {
    // Change the block name below to "block_<bid>" where <bid> is the
    // block id of your custom block.
    $block = new Block('block_1');

    // "sidebar_first" is the machine name of Sidebar First region in
    // the theme we are using. If the machine name of the region in
    // which you have placed the block is different, then replace
    // "sidebar_first" below by it.
    $this->assertTrue(
      $block->isPresent('<front>', 'sidebar_first'),
      "Homepage block is not present on the homepage."
    );

    $this->assertFalse(
      $block->isPresent('user/login', 'sidebar_first'),
      "Homepage block is present on /user/login page."
    );

    // Make sure that block title matches.
    $this->assertEquals("Homepage block", $block->getSubject('<front>'));

    // Make sure that block body is as expected. Note that we are comparing
    // against "<p>Block body</p>" and not "Block body". That's because
    // we use Filtered HTML format when creating the block body. This text
    // format automatically adds <p> tags around the body. If you have used
    // plain text format, then you will need to compare against "Block 
    // body".
    $this->assertEquals('<p>Block body</p>', $block->getMarkup('<front>'));
  }
}

7) 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/blocks". Here is how the phpunit.xml file will look:

<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.6/phpunit.xsd"
         backupGlobals="false"
         backupStaticAttributes="false"
         cacheTokens="false"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         forceCoversAnnotation="false"
         mapTestClassNameToCoveredClassName="false"
         processIsolation="false"
         stopOnError="true"
         stopOnFailure="true"
         stopOnIncomplete="false"
         stopOnSkipped="false"
         verbose="true">
    <testsuites>
        <testsuite name="ParaTest Fixtures">
                <directory>./RedTest/tests/blocks</directory>
        </testsuite>
    </testsuites>
</phpunit>

8) Now is the time to run the test. Go to <DRUPAL_ROOT> folder and execute the test:

cd <DRUPAL_ROOT>
tests/bin/paratest --phpunit=tests/bin/phpunit --processes=4 --no-test-tokens --log-junit="tests/output.xml" --configuration=tests/phpunit.xml

You should see the following output:

Running phpunit in 4 processes with tests/bin/phpunit

Configuration read from /Users/neeravm/Sites/drupal7/tests/phpunit.xml

.

Time: 1.12 seconds, Memory: 30.25Mb

OK (1 test, 4 assertions)

That's it. You have an automated test for your custom block. Run it every time you change anything in your Drupal application and you'll minimize bugs on production by at least 95%.

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 admin@redcrackle.com. I can help you with the setup. If the test passed, then write a comment and note down how much time it took to run the test!

If you are interested in learning more about how to test your Drupal application using this integration testing framework, here are some articles that might be of interest to you:

Ready to get Started?