What I Learned Today: Drupal Behat Scenario Cleanup

I've been doing a lot more Behat testing recently. As my tests have gotten more complex, I've discovered that it was only a matter of "luck" that my earlier tests were properly cleaning up after themselves. What I mean, is that during my tests I fill out and submit a node form, checking that I successfully created it and that the appropriate users can see it. After each scenario you want to clean up any data that was created so you can run the test again and get the same result. The way the Drupal Behat extension works, it tracks nodes, users, roles and taxonomy terms you create using its methods, so that in its @AfterScenario function knows which nodes to delete. The problem is that when you submit the form using steps like the ones below, the extension does not track those nodes:

Given I am logged in as a user with the "administrator" role
And I am on the Content Creation page
When I click on "Basic page"
And I enter "BDD TEST BASIC PAGE" for "Title"
And I enter "BDD TEST BODY CONTENT..." for "Body"
And I press "Save"
Then I should see "The Basic page \"BDD TEST BASIC PAGE\" was created"

So how does this simple scenario clean-up after itself just fine? The reason is that the test creates a fake user and gives it the "administrator" role, tracking that user. When all the other steps are completed, they are completed as that user. In the after scenario, the user is deleted and the option to delete all the users content is passed in.

So what is causing some of my scenarios to not cleanup? Taxonomy terms were a particular area I noticed. I was doing something similar to the above and submitting the Add Term form. The term is now untracked and deleting the user will not automatically (or even optionally) delete their taxonomy terms or files.

Given I am logged in as a user with the "administrator" role
And I am on "admin/structure/taxonomy/category"
When I click "Add term"
And I enter "BDD TESTING CATEGORY" for "Name"
And I press "Save"
Then I should see "Created new term BDD TESTING CATEGORY"

A solution is to create an after scenario in FeatureContext.php that deletes terms match an expected pattern. For instance, I prefix all my entities with BDD TEST and in the cleanup method I delete all terms that match.

/**
 * Remove terms that we probably created. Nodes
 * are handled because when a user is deleted their content
 * is deleted as well. This not true for terms
 * that they create though.
 *
 * @AfterScenario
 */
public function cleanupTerms() {
  $query = new EntityFieldQuery();
  $result = $query->entityCondition('entity_type', 'taxonomy_term')
    ->propertyCondition('name', 'BDD TESTING', 'STARTS_WITH')
    ->execute();
  if (isset($result['taxonomy_term'])) {
    $tids = array_keys($result['taxonomy_term']);
    foreach ($tids as $tid) {
      taxonomy_term_delete($tid);
    }
  }
}

Comments

We use a more generic approach, with a step definition 'And I intend to create a "node" titled "some test title". This goes before your form manipulation and submission. The step itself just stores the titles in a property on the feature context object. Then we make our feature context's afterScenario extend the base Drupal context one. In our after scenario we use node_load_multiple to load the nodes by title and add them to Drupal context's nodes property, then we just delegate to the parent after scenario and it cleans them up for us. Because the entity type is also a parameter, this can also handle terms and users if needed.

Just remember that this entity query is executed likely as an "anonymous" user, so make sure to consider you may not get all the results you want if any entities are not accessible to anonymous users and would be filtered out of the query. In D8, use ->accessCheck(FALSE) and for D7 use ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT').

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <cpp>, <java>, <php>. The supported tag styles are: <foo>, [foo].
  • Web page addresses and email addresses turn into links automatically.
  • Lines and paragraphs break automatically.

Ready for transformation?