Check your version

This video covers a topic in Drupal 7 which may or may not be the version you're using. We're keeping this tutorial online as a courtesy to users of Drupal 7, but we consider it archived.

Alternate resources: 

Creating Dummy Content with SimpleTest

Video loading...

  • 0:01
    Automated Testing in Drupal 7 with SimpleTest
  • 0:03
    Creating Dummy Content with SimpleTest
  • 0:05
    with Joe Shindelar
  • 0:08
    Running and writing tests against a Drupal site
  • 0:10
    with no content is only going to get us so far.
  • 0:13
    There's really not much to do on a Drupal site
  • 0:15
    that doesn't have any content.
  • 0:17
    Eventually we're going to need to start creating dummy content
  • 0:21
    within the context of our test environment,
  • 0:24
    in order to complete our tests.
  • 0:26
    There's another set of really useful helper methods
  • 0:29
    that we haven't looked at yet, which are geared towards creating
  • 0:33
    dummy content for testing, including simple tasks like generating
  • 0:37
    random strings or random names of a specified length, and more complex
  • 0:42
    things, like creating nodes.
  • 0:44
    In this lesson, we'll look at the various helpers
  • 0:47
    for creating random content within SimpleTest,
  • 0:50
    then we'll go ahead and use those tools to test the Drupal core
  • 0:53
    Statistics module's functionality by creating a piece of content
  • 0:57
    and viewing it multiple times to ensure the stats
  • 1:00
    counter is appropriately incremented.
  • 1:03
    By the end of this lesson, you should
  • 1:04
    be able to explain the difference between, and make
  • 1:08
    use of, the random string and random name generators,
  • 1:12
    and know how to create dummy content with the drupalCreateNode helper
  • 1:16
  • 1:18
    As per usual, I think it probably makes sense for us
  • 1:21
    to start by taking a look at the documentation for the functions
  • 1:25
    that we're going to be talking about in this lesson.
  • 1:29
    So if you go to,
  • 1:33
    you scroll down towards the bottom of the page.
  • 1:35
    We're going to click on the link for Testing Reference.
  • 1:38
    And then from there we're going to scroll down again
  • 1:40
    and click on the link for API Functions.
  • 1:44
    All of these methods and functions are
  • 1:46
    documented on as well.
  • 1:48
    I find this reference here to be a little bit easier to understand,
  • 1:52
    and really kind of cuts right to the essential parts.
  • 1:55
    So we're going to be talking about the randomName, randomString,
  • 1:59
    and drupalCreateNode members of the DrupalWebTestCase.
  • 2:04
    If I scroll down this page a bit, we can
  • 2:06
    find the documentation for those.
  • 2:08
    So we've got $this->randomString, randomName.
  • 2:13
    There's a createContentType, which we're not going to talk about,
  • 2:15
    but is also useful.
  • 2:17
    And the drupalCreateNode.
  • 2:18
    All three of these that we're talking about
  • 2:21
    are geared towards allowing us to generate
  • 2:24
    content in order to use with our tests.
  • 2:27
    Sometimes that content is just a random string like a username.
  • 2:30
    For example, when you do the drupalCreateUser method, what it's doing
  • 2:35
    in the background is calling Drupal random-- or this randomName
  • 2:39
    in order to generate a random username and password as well.
  • 2:43
    There is randomString and randomName.
  • 2:45
    Both of them return a string of text that's randomized.
  • 2:50
    The difference between the two is that randomString will also
  • 2:54
    include non-alphanumeric characters.
  • 2:57
    So special characters, like the pound sign, or an exclamation,
  • 3:00
    or a dollar sign, are included in randomString.
  • 3:03
    Whereas randomName is only alphanumeric characters,
  • 3:07
    and it's also guaranteed to always start with a alphabet character,
  • 3:11
    not with a number.
  • 3:13
    This is nice because there are some instances, especially given
  • 3:16
    PHP, where we need strings that we are guaranteed start
  • 3:20
    with an alphabetical character, not with a number.
  • 3:24
    So understanding that difference is important.
  • 3:27
    Otherwise, they function the same way.
  • 3:29
    You pass in an optional single argument
  • 3:32
    that is the number of characters that you
  • 3:34
    would like to include in that string.
  • 3:36
    The default is eight for both, but you can make it any number.
  • 3:40
    So we'll look at using those.
  • 3:42
    And then there's the drupalCreateNode node method.
  • 3:46
    The drupalCreateNode method is used to help us quickly
  • 3:49
    create a node of any particular type.
  • 3:52
    So rather than having to navigate to the node creation form,
  • 3:55
    and fill out the form, and click the Submit button,
  • 3:57
    we're going to manually create the node.
  • 4:00
    We describe the node as an array of key value pairs,
  • 4:03
    things like node type and title are the keys,
  • 4:07
    and then the values are what we'd like that to be assigned.
  • 4:10
    Then we can use drupalCreateNode to create that node.
  • 4:14
    And it will actually return the node object for us.
  • 4:17
    You can see a couple examples of this in the documentation here.
  • 4:20
    And also the nice thing is, it shows you what the default settings are.
  • 4:24
    So when you call drupalCreateNode, you
  • 4:25
    can pass it an array of the values that you would
  • 4:28
    like to use when creating that new node.
  • 4:30
    Any that you leave out will default to what you see in the list here.
  • 4:34
    Let's take a look at our code and make
  • 4:36
    use of some of these methods in our test cases.
  • 4:40
    I'm going to switch over to my text editor, quick,
  • 4:43
    and I'm going to open up the helloworld.test file that we
  • 4:46
    created in previous lessons in the series.
  • 4:49
    This contains all of our tests that we've written so far.
  • 4:52
    Remember, in the last lesson we actually added an underscore
  • 4:55
    to a bunch of the test methods.
  • 4:56
    This means that, by doing so, the SimpleTest module isn't finding
  • 5:01
    these sets of tests and running them, because they're no longer
  • 5:05
    prefixed with the word Test for these methods.
  • 5:09
    What I want to do is find the one where
  • 5:11
    we previously altered the site name.
  • 5:15
    So we did that here, in testAuthorization,
  • 5:17
    actually in the previous lesson.
  • 5:19
    What this test does is, it logs in as an administrative user,
  • 5:23
    it navigates to the site information settings page,
  • 5:26
    and it changes the name of our site.
  • 5:27
    And then it saves the form, and verifies
  • 5:30
    that the site name is as expected.
  • 5:33
    Rather than hard coding the name here,
  • 5:34
    let's just generate a random name.
  • 5:37
    So I'm going to say $site_name = $this->randomString();
  • 5:41
    we'll get a random string.
  • 5:43
    And we kind of want ours to be 10 characters instead of eight.
  • 5:47
    So I assign this to the variable $site_name,
  • 5:50
    and then I'm going to use that variable when assigning the value
  • 5:53
    of site_name when submitting the form.
  • 5:55
    The reason that I've put it in a variable like this,
  • 5:59
    is because I want to make sure that I'm storing the randomly generated
  • 6:02
    string, so that I can make use of it later, when I perform my test
  • 6:06
    to assert that the string was actually used.
  • 6:09
    So down here in Testing Site Name, I might do something like $site_name.
  • 6:15
    If we switch over to our browser and run these tests,
  • 6:18
    we can see that it'll generate a random string,
  • 6:20
    assign it as the site name, and assert
  • 6:22
    that that is the actual site name.
  • 6:25
    Let's try that.
  • 6:25
    So back on our site, I'm going to go to Configuration, Testing,
  • 6:30
    find the Hello World tests.
  • 6:32
    There's just one still, so I'll just check the box for the Hello
  • 6:35
    World group, and click Run Tests.
  • 6:37
    And wait for the tests to complete.
  • 6:41
    Once the tests are complete, we can take a look
  • 6:43
    at the verbose messages that were output by this test.
  • 6:47
    So it logged in as our user, navigated to the form here,
  • 6:51
    let's see-- navigated to the form to edit the system site information.
  • 6:57
    So I can see that.
  • 6:59
    I'm on the form.
  • 7:00
    Click Next, you can see it's submitted the form here.
  • 7:04
    And it's submitted the form with a random string for the site
  • 7:07
    name, which is what we asked it to do.
  • 7:09
    You can also see right away that after that form was submitted,
  • 7:12
    it's changed the site information variable,
  • 7:14
    and that random string is showing up.
  • 7:16
    And on the next page, we're back to the home page
  • 7:18
    and we run our assertion that, yep, the site name
  • 7:21
    is definitely set to this randomString.
  • 7:23
    So we know that's working.
  • 7:25
    Let's take a look at generating some other content.
  • 7:27
    In order for this test to make sense,
  • 7:29
    I want to walk through what we're going to do in the browser.
  • 7:32
    I want to test some functionality of Drupal's core Statistics module.
  • 7:36
    Let's take a look at what that module does.
  • 7:38
    First thing I'll do on my site is just enable the Statistics module.
  • 7:42
    That's not already enabled.
  • 7:44
    So I'll scroll down, go to Modules, scroll down the list,
  • 7:48
    find the Statistics module, and enable it.
  • 7:52
    Save Configuration.
  • 7:53
    Now I'm going to add a piece of content to my site.
  • 7:55
    I'm going to go to Add Content, add a Basic Page.
  • 7:59
    We'll call this Test Page.
  • 8:02
    Say, copy goes here in the body.
  • 8:05
    Leave everything else the defaults, and I'll click Save.
  • 8:10
    Taking it back to the page that I just created,
  • 8:12
    and I'm going to hit Refresh.
  • 8:14
    It looks like I need to enable some tracking
  • 8:17
    with the Statistics module.
  • 8:18
    So the module is turned on, but I need to configure it.
  • 8:22
    So if I go to Configuration, and then Statistics,
  • 8:26
    and I can Enable Access Log, and I'm going to say Count Content Views.
  • 8:32
    And Save Configuration.
  • 8:34
    Close this overlay, refresh the page.
  • 8:38
    Now you can see, down in the bottom right corner here,
  • 8:40
    it says one read.
  • 8:41
    If I refresh it again, it says two.
  • 8:43
    If I continue to refresh it, that number will keep going up.
  • 8:46
    This is what the Statistics module does.
  • 8:49
    So in order to test this, the plan that I need to execute
  • 8:54
    involves first, I need to enable the Statistics module.
  • 8:58
    Then I need to configure the Statistics module so
  • 9:01
    that statistics tracking is turned on.
  • 9:03
    And the little counter shows up in the corner down here.
  • 9:07
    Then I need to create a new node so I can simulate navigating
  • 9:11
    to that page in my browser and clicking Refresh a couple of times,
  • 9:15
    and ensuring that the counter goes up.
  • 9:18
    Let's take a look at how we would do that in our test case.
  • 9:22
    So I'm going to switch back to my editor.
  • 9:23
    I'm going to add an underscore to our test authorization
  • 9:27
    method just so that it skips running it when we're testing the Create
  • 9:31
    Content one we're about to write.
  • 9:33
    Add a new testCreateContent, remembering
  • 9:35
    to prefix the method name with test.
  • 9:38
    That way SimpleTest will treated as a set of tests that it should run.
  • 9:43
    And I'm going to go through all the things that I need to do.
  • 9:47
    So the first thing we said we need to do
  • 9:49
    is enable the Statistics module.
  • 9:51
    That doesn't happen inside of our test method, that's
  • 9:54
    actually part of the set up method.
  • 9:56
    So I'll scroll back up here.
  • 9:57
    We're already enabling Hello World.
  • 9:59
    Let's also enable-- like so.
  • 10:01
    So I'm enabling the Hello World module, and the Statistics module.
  • 10:05
    I also said that one step that we're going to need to do
  • 10:07
    is configure the Statistics module.
  • 10:10
    Now, there are a couple of ways we could go about doing this.
  • 10:13
    We could navigate to the Statistics configuration form,
  • 10:17
    and fill out the form and change the settings.
  • 10:19
    But since that's not-- we're not really
  • 10:20
    trying to test the functionality of that form.
  • 10:23
    We could also just use the variable set function provided by the Drupal
  • 10:27
    API, and manually set those variables
  • 10:30
    to whatever we want them to be.
  • 10:32
    I'm going to do that inside of my setup method here.
  • 10:35
    So I'm going to add variable_set, statistics_enable_access_log,
  • 10:39
    and statistics_count_content_views.
  • 10:42
    I'm setting them to on.
  • 10:44
    This is the equivalent of having gone and checked the check box,
  • 10:46
    but far fewer steps for the test runner to perform.
  • 10:50
    So this'll be more performant.
  • 10:52
    Whenever you manipulate variables inside of a test case,
  • 10:55
    you also need to use the refreshVariables method.
  • 10:59
    You need to call this refreshVariables.
  • 11:01
    And what this does is update the TestCase's
  • 11:04
    cached version of all of the variables.
  • 11:06
    So these three lines here are the equivalent
  • 11:08
    of having gone and enabled the statistics tracking
  • 11:11
    on the configuration form for the Statistics module.
  • 11:15
    So we did those two steps.
  • 11:16
    The next thing we need to do is actually create a piece of content,
  • 11:20
    and go and view it.
  • 11:21
    So down here, at the bottom of our helloworld.test file,
  • 11:25
    inside of the testCreateContent method,
  • 11:27
    let's go about creating a new node.
  • 11:29
    In order to do that, we need to use this drupalCreateNode method.
  • 11:35
    So we'll say $node = $this drupalCreateNode.
  • 11:40
    And we saw that it takes one argument.
  • 11:42
    The argument we need to pass in here is the settings for our node.
  • 11:46
    What are those settings?
  • 11:48
    It's the values that we want for each of the individual fields,
  • 11:51
    and properties of a node.
  • 11:53
    It might look something like this.
  • 11:54
    I'll create a new settings array, and we'll
  • 11:57
    say we want a node of "type" "page."
  • 11:59
    That's the default, but just to illustrate how this works.
  • 12:01
    Maybe we want to promote it to the home page.
  • 12:04
    We want to set the title to, well, I don't know.
  • 12:08
    We need a string.
  • 12:09
    We could either just add our own string
  • 12:11
    or we could come up with a random string
  • 12:13
    by using something like $this randomName.
  • 12:17
    We'll also want to fill in the body field.
  • 12:19
    It's not required, but I want to illustrate how this works.
  • 12:23
    So the body field of a node is a little bit more complicated.
  • 12:27
    First off, it's a field API field, it's
  • 12:29
    not just a standard entity property.
  • 12:31
    So we need to simulate the structure that you
  • 12:34
    would see in a node object.
  • 12:37
    Ultimately what we're doing is we're kind of creating a base node
  • 12:41
    object, passing it into the drupalCreateNode function, which
  • 12:44
    will then save that object to the database.
  • 12:48
    So the body field on a node, when you're accessing it,
  • 12:51
    usually looks something like this, body,
  • 12:54
    und, U-N-D, zero, oh, probably value.
  • 12:59
    And it also contains the format options.
  • 13:03
    So it's this nested array that contains the field information.
  • 13:07
    We need to simulate that here when creating
  • 13:10
    a new node using drupalCreateNode.
  • 13:12
    So I'll say, new array.
  • 13:14
    Body is an array.
  • 13:16
    The first key is LANGUAGE_NONE, that's that U-N-D.
  • 13:23
    And that's an array.
  • 13:25
    So this is zero, here, and zero then, is an array as well.
  • 13:30
    And inside of that array we've got the value.
  • 13:34
    Or we could say, Copy goes here.
  • 13:37
    And the format, the format being, which
  • 13:39
    text filter to use with this body field.
  • 13:42
    I'm just going to say filter_default_format, which will
  • 13:47
    just ask Drupal for whatever the default format setting is.
  • 13:52
    So now when this settings array gets passed through drupalCreateNode,
  • 13:56
    I expect it to create a new page node with the title that's
  • 13:59
    some random string, and the body copy
  • 14:01
    being "copy goes here," using the default format.
  • 14:05
    It's promoted to the front page.
  • 14:07
    That looks good to me.
  • 14:08
    So that's going to create our node.
  • 14:11
    The nice thing about doing it this way, with drupalCreateNode,
  • 14:13
    rather than going and filling out the form,
  • 14:15
    is we also now know what the node object is.
  • 14:19
    So we'll know the idea of the node that was just created,
  • 14:21
    which means we can really easily navigate
  • 14:23
    to the page to view that node.
  • 14:27
    So I can navigate to that page in my test by doing something like,
  • 14:31
    $this >drupalGet('node/ ' , $node >nid);
  • 14:36
    So I've just navigated to that page.
  • 14:38
    Once I'm on the page, I can assert that I'm actually on the right page
  • 14:42
    by saying, $this, assertText($title, 'Node title was found.')
  • 14:49
    So we're verifying that we're on the right page
  • 14:52
    just by comparing the title of the page
  • 14:55
    that we're viewing, to the title of the node that we just created.
  • 14:58
    And then I can view the page a couple of times,
  • 15:02
    and see if that assert-- or the one read, two reads,
  • 15:06
    statistic is displayed and goes up.
  • 15:08
    So I might do something like this.
  • 15:14
    So I'm going to view the page a second time.
  • 15:16
    The reason I'm doing it a second time
  • 15:18
    is, that one read statistic doesn't actually show up
  • 15:21
    until the second time you view the page.
  • 15:22
    Because someone has to have previously viewed it,
  • 15:25
    in order for there to be one read.
  • 15:27
    And I'll do $this >assertText('1 read', 'Stats module
  • 15:29
    shows 1 read.') like so.
  • 15:37
    You know what?
  • 15:38
    I'll just copy this again, and do it a second time,
  • 15:41
    to confirm that if I view the node a second time,
  • 15:44
    the counter is incremented.
  • 15:46
    One other important thing here is that, in order for this one read
  • 15:50
    and two reads to show up, we need to be an authenticated user
  • 15:53
    with permission to view that counter.
  • 15:56
    Right now, all of this is happening as the anonymous user.
  • 15:59
    In a previous lesson, we saw how you can
  • 16:01
    authenticate and authorize a user.
  • 16:03
    What I'm going to do is update our user that we created earlier,
  • 16:07
    and give them permission to view these statistics,
  • 16:11
    and then log in as that user.
  • 16:13
    If I scroll back up to the setup method
  • 16:15
    where we're creating our admin user, we've got this drupalCreateUser.
  • 16:19
    They're getting "administer site configuration" permission.
  • 16:22
    I'm also going to give them "access content," so they can view
  • 16:25
    the content that we just created, and "view
  • 16:28
    post access counter" permissions.
  • 16:32
    So our admin user now has this whole set of permissions.
  • 16:37
    Down in our test method that we just created,
  • 16:39
    I now need to log in as that user.
  • 16:42
    So I'll just go ahead and add that right at the top here.
  • 16:45
    It doesn't really matter, as long as I do it
  • 16:47
    before I get to this "1 read" step.
  • 16:49
    But to keep things tidy, we'll just say drupalLogin $this_admin_user.
  • 16:59
    So that should work.
  • 17:00
    Let's go and run this test and see what happens.
  • 17:03
    Back in my browser I can go to Configuration, Testing,
  • 17:09
    find the Hello World test in the list,
  • 17:11
    and click the Check box for Hello World group.
  • 17:13
    We'll run that whole group of tests, because it's really just our one,
  • 17:16
    and then click the Run Tests button, and wait
  • 17:18
    for SimpleTest to do its thing.
  • 17:21
    What SimpleTest is doing right now, is setting up an environment that
  • 17:24
    has the Statistics module enabled, then logging in as the admin user
  • 17:28
    with the set of permissions that we just
  • 17:29
    defined, configuring the Statistics module by simulating checking
  • 17:35
    those two check boxes, and then creating a node
  • 17:38
    and viewing the node a couple of times to test the counter.
  • 17:41
    It looks like all of our tests pass.
  • 17:43
    That's awesome.
  • 17:45
    You click this Hello World open, you can take a look at what it's done.
  • 17:49
    We've seen this part before, where it creates the user
  • 17:51
    and logs in as that user.
  • 17:53
    Here's where it's created our node.
  • 17:55
    So it's just logged in as this new user.
  • 17:58
    I can go Next, it's just created our node,
  • 18:01
    and gone and viewed the node for the first time.
  • 18:04
    It's verifying that the title is that random string.
  • 18:07
    There is no one read yet.
  • 18:09
    But if I go to the next page, this is the second time
  • 18:12
    we viewed it, so there's one read.
  • 18:14
    This is the third time we viewed the same page, so there's two reads,
  • 18:17
    and that's the end of our test suite there.
  • 18:19
    So that worked out well.
  • 18:22
    Just to recap what we did, and what we looked at here,
  • 18:25
    the most important bits were the randomString, randomName,
  • 18:30
    and drupalCreateNode methods that we're using inside of our tests.
  • 18:34
    I'm going to take a look at the code again.
  • 18:37
    This randomName and this randomString
  • 18:39
    are great if we need to just generate some random bits
  • 18:42
    of content, to create a new user, or as the title of a page,
  • 18:46
    or wherever you just might need something random within the test.
  • 18:50
    Sometimes we need more structured content, though, like a node.
  • 18:53
    The DrupalWebTestCase provides us with the drupalCreateNode method,
  • 18:57
    which helps make it easier to create notes.
  • 19:00
    We set one up here by creating a settings array that we pass in,
  • 19:04
    that defines the properties and field values.
  • 19:07
    We created a page node.
  • 19:08
    I could just as easily change this to say
  • 19:10
    article, and create an article node.
  • 19:12
    Or I could create a new node type, and then
  • 19:15
    create a note of that type.
  • 19:17
    Be aware when creating nodes, that if you're dealing with fields
  • 19:21
    on the node, you need to format the value in this settings array
  • 19:26
    just as you would do with the node, if you are calling say, node save.
  • 19:31
    A really good way to figure out what values, or what structure,
  • 19:34
    this should be, is to actually go to your site,
  • 19:37
    log in and create a node, and use a module like Devel, which has
  • 19:41
    the preview of what this node object looks like, and inspect that.
  • 19:46
    Or just write some code that does a var dump on a node object,
  • 19:49
    to see how Drupal handles that.
  • 19:52
    And then simulate that structure inside of your test.
  • 19:55
    So that's creating random content inside of SimpleTest.

Creating Dummy Content with SimpleTest


There's another set of really useful helper methods that we haven't looked at yet which are geared towards creating dummy content for testing. Including simple tasks like generating random strings, or random names of a specified length, and more complex things like creating nodes, or even new content types. In this lesson we'll take a lot at the various helper methods in DrupalWebTestCase that assist in the creation of dummy content by creating various pieces of random content and then testing functionality based on that content.

In order to demonstrate these tools lets look at writing some tests for the core statistics module which amongst other things tracks page views for content. In order to perform these tests we're going to need a piece of content that we can view, and then view again to ensure that the statistics are properly updating.

Creating random strings can be done with DrupalWebTestCase::randomName() and DrupalWebTestCase::randomString(). Both methods take an argument that allows you to set the number of characters that should be returned, or you can just leave out to get the default. The difference between the two is that DrupalWebTestCase::randomName() will only use alphanumeric characters and the returned string will always start with a letter. This is useful for things like generating random usernames or email addresses, or other things that don't allow for special characters.

The DrupalWebTestCase::drupalCreateNode() helper can be used to create nodes. While you could navigate to and fill out the form using SimpleTest this is much quicker and requires far less code. Here's an example of creating a node:

$title = $this->randomName();
$settings = array(
 'type' => 'page',
 'promote' => 1,
 'title' => $title,
 'body' => array(LANGUAGE_NONE => array(
     'value' => 'Copy goes here',
     'format' => filter_default_format(),
$node = $this->drupalCreateNode($settings);

This will create a new page node with a random title and the string "Copy goes here" in the body field. The array of values passed to DrupalWebTestCase::drupalCreateNode() should mirror the structure of a node object. If you're unsure what that structure is one easy way to figure it out is to use node_load() to retrieve an existing node and inspect the returned object.

Log in or sign up to download companion files.