This tutorial covers writing a "Hello World" test for Drupal 7 using the SimpleTest framework that comes with Drupal core, and is based on the free video Learning Test Case Basics by Writing A Hello World Test. Knowing how to write tests is an important skill, and being able to do so can help to increase the quality of your code, and save you hours of time clicking around your site making sure things still work after making changes.
For example, we've got a feature on our site that allows anyone to embed a copy of any of our free videos into another site. It's a great feature, but to be honest, it's also one that we forget about. It's hidden beneath the "share" link on video pages, and it's not something that any of us do very often. Whenever we make changes to our video player we're diligent about testing them on our site, but often times forget to check the embed codes. Testing them is also a bit of a tedious process because you need to find a free video, find the embed code, copy it into an HTML file on another site, and then test it. As such, we tend to break it from time to time without realizing we've done so until much later.
After having done this a couple of times though, we added test coverage for it. So now, whenever we make changes to any part of the site, one of the things that happens before that change is made live is we subject a copy of the site with the changes applied to a barrage of automated tests. If we break that embed code again (which we have), we'll know about it before it becomes a problem on the live site.
This is just one of the many useful things you can do with automated tests. Learn more in our new series, Automated Testing in Drupal With SimpleTest. Keep reading to learn how to write your first test.
After completing this tutorial you should be able to:
- Create a new PHP class that defines a test
- Provide Drupal with meta-data about your test
- Run your test to see if it works
Background
This tutorial assumes that you are familiar with PHP and basic OOP concepts, and that you've written a Drupal module before and know how to get Drupal to recognize your module and allow it to be enabled. If you need to brush up on any of these things check out our Module Development for Drupal 7 series.
Hello World
- Start by creating a simple
helloworld
module directory in sites/all/modules/custom/helloworld/ - Add a helloworld.info file with the following contents:
name = Hello World description = An example module to demonstrate using SimpleTest core = 7.x
- Add a helloworld.module file with the following contents:
<?php /** * @file * Hello World demonstrates the use of SimpleTest for Drupal 7. */ /** * Implements hook_menu(). */ function helloworld_menu() { $items = array(); $items['helloworld'] = array( 'title' => 'Hello World', 'access callback' => TRUE, 'page callback' => 'helloworld_hello_page', 'type' => MENU_NORMAL_ITEM, 'menu' => 'navigation', ); return $items; } /** * Page callback for /helloworld. */ function helloworld_hello_page() { return t('Hello World. Welcome to Drupal.'); }
- In the Administration menu, go to Modules (admin/modules).
- Enable the Hello World module.
- In the navigation menu navigate to Hello World (helloworld), where you should now see the text "Hello World: Welcome to Drupal." displayed on the page.
This is what we're going to write a test for. Ensuring that when our module is enabled, a user can navigate to the page /helloworld and see this text. Let's get started.
Extending DrupalWebTestCase
Any module can optionally contain one or more test cases, and those test cases can either all be in a single file, or spread out among many files. The convention is for files that contain tests to end with the .test
extension. And if you've only got one, to name it MYMODULE.test.
- Start by creating a new file: helloworld/tests/helloworld.test, we will add the code that makes up our test case to this file.
- All functional tests in Drupal should extend the
DrupalWebTestCase
class which will provide the utility functions used to drive the test browser, helper functions for interacting with a Drupal application, and all the assertions we will use to perform our actual tests. - Add the following to your helloworld.test file:
<?php /** * @file * Tests for the hello world module. */ class HelloworldTests extends DrupalWebTestCase { }
- Add a
getInfo()
method to yourHelloworldTests
class. This method returns an array that provides meta-data about our test that the SimpleTest module can use when displaying our test in the UI. This method is required in order for your test to work.
/** * Metadata about our test case. */ public static function getInfo() { return array( // The human readable name of the test case. 'name' => 'Hello World', // A short description of the tests this case performs. 'description' => 'Tests for the Hello World module.', // The group that this case belongs too, used for grouping tests together // in the UI. 'group' => 'Hello World Group', ); }
- Add a
setUp()
method toHelloworldTests
. This method is called when the system is preparing the environment for running our tests. It allows us to perform any setup steps required. In this case, we need to ensure that our module is enable during setup so that the page we want to test is available. We can do this by calling the parent classes'ssetUp()
method and passing it an array of modules we want enabled.
/** * Perform any setup tasks for our test case. */ public function setUp() { parent::setUp(array('helloworld')); }
- Add a
test*()
method to our class. Each test case can have one or more methods whose names are prefixed with the string test. Each of these methods will be automatically called by the SimpleTest test runner, and should contain the various assertions required in order to demonstrate that this test is passing. This example will use theDrupalWebTestCase::drupalGet()
method in order to tell the internal browser to navigate to the URL /helloworld. And then use theDrupalWebTestCase::assertText()
method to verify that the string, "Hello World ...", exists somewhere in the HTML output of the page the internal browser is currently looking at.
public function testHelloWorld() { // Navigate to /helloworld. $this->drupalGet('helloworld'); // Verify that the text "Hello World ...", exists on the page. $this->assertText('Hello World. Welcome to Drupal.', 'The page content is present.'); }
- Finally, we need to tell Drupal about our new test. Update your helloworld.info file and add the following line so that after clearing the cache the registry will contain a reference to our new
HelloworldTests
class.
files[] = tests/helloworld.test
Run your tests
- Clear the cache so Drupal locates our new test(s). Navigate to Configuration > Performance (admin/config/development/performance) in the Toolbar, and then clicking the "Clear all caches" button.
- Navigate to Modules (admin/modules) in the Toolbar. Enable the Testing module in the Core section.
- Navigate to Configuration > Testing (admin/config/development/testing).
- Select the checkbox for the "Hello World" test to run all tests in this group, or alternately tip the drop down open and choose the individual test case you want to run.
- Click the "Run tests" button.
- A new page will open and display a progress bar while your tests run.
- Once completed, you will be directed to a page with a table that shows the results of your tests.
Summary
In this tutorial we've written a Hello World test in order to demonstrate some of the fundamental concepts necessary for writing tests for Drupal with SimpleTest. Including, defining our HelloworldTests
class in a .test
file and making sure Drupal can find it by adding it to our module's .info
file. Then providing meta-data about our tests for the SimpleTest UI, and any setup instructions necessary so that the environment in which our tests run is appropriate for our test case. Finally, we wrote a test*()
method that used the internal SimpleTest browser to navigate to a page and verify that a string of text is present on that page.
I encourage you to explore SimpleTest through the Testing module in Drupal, and the concept of automated testing further as it provides numerous sanity and time saving benefits. Enjoy.
Comments
Clear. Concise. Informative. And to the point. Well done!
Nice intro to tests. Been a Drupal dev for many years now and never written a test, tis about time I started.
Really nice post:) How about testing more complicated stuff like hooks (node_update, query_alter) etc? It would be very nice to see how to do that correctly:)
Hey Chris, glad you enjoyed the article. We've actually got a whole series on SimpleTest that covers a lot of the more advanced features. https://drupalize.me/videos/learning-test-case-basics-writing-hello-wor…. It doesn't cover these specific use cases but would give you a good push in the right direction.
Another place to find more information would be to look through Drupal core's test files and find ones that are similar to your use case. There are thousands of tests in core, and a lot of them are already testing things like hook_node_update and hook_query_alter so you can probably build off of what is already being done.
it is really very useful information for the user.
Thanks for the information.
Add new comment