Get a working behaviour-driven test suite in under ten minutes

You should be developing using some kind of test harness: that way you know that what you're doing right now is unlikely to have broken what you did six days or six months ago. Better still, you know what you did six days or six months ago far more completely, because the tests fleshed out the specification at the time and provide a clear, documenting definition of the functionality for your current purposes.

But setting up tests, especially in behaviour-led and tightly-coupled systems like Drupal, is hard, right? Well, my recent experience on a project (more about that later) has taught me that not only is it absolutely worth setting up a behaviour-driven test suite, but that doing so is really straightforward these days.

Here's how to set up Behat testing, and have an example test running, in under ten minutes. You can apply this tutorial to a new project, to a project in development, to a project under ongoing maintenance, and even to a non-PHP or non-Drupal project, and it will be worth it.

Download Behat with the Drupal extension

It's 2015 and this is a predominantly Drupal blog, so I'm going to assume you've got composer already installed. If you're not sure about that or anything below, there is fuller documentation available. (Other non-PHP BDD frameworks also exist, but I don't cover them here.)

To set up a Behat project which is fully Drupal-aware, first create a project folder. Everything that follows will be assumed to be happening within that folder, so if you're working at a terminal, cd into the folder before you run anything below.

Add a very simple composer.json file to this folder:

{
  "require": {
    "drupal/drupal-extension": "~3.0"
},
  "config": {
    "bin-dir": "bin/"
  }
}

From a terminal window, run composer install, and Behat should "just install", along with Mink and the Drupal extension.

Initialize Behat and add a configuration YAML file

Run bin/behat --init and it will set up a features/ subfolder for you, with some stub PHP classes you can ignore for now.

Next, add a behat.yml file at the top level:

default:
  suites:
    default:
      contexts:
        - FeatureContext
        - Drupal\DrupalExtension\Context\DrupalContext
        - Drupal\DrupalExtension\Context\MinkContext
        - Drupal\DrupalExtension\Context\MessageContext
        - Drupal\DrupalExtension\Context\DrushContext
  extensions:
    Behat\MinkExtension:
      goutte: ~
      selenium2: ~
      base_url: http://www.google.co.uk
    Drupal\DrupalExtension:
      blackbox: ~

This looks like a lot of detail, but don't panic: most of this is boilerplate from the more in-depth documentation I linked to above. The only thing you need to worry about for the purposes of this tutorial is the base_url: parameter.

We set it to a Google address, to make the test below work. You can do that too, initially, but you'll want to test your local build eventually instead.

Add your first test

Within the features/ subfolder that was created by the --init step above, add the following as a file features/navigate.feature:

Feature: Navigate website.
  In order to begin working with my website
  As a site visitor
  I need to be able to navigate around the site
 
  Scenario: Access advanced search
    Given I am on the homepage
    When I click "Advanced search"
    Then I should see "all these words:" in the "label[for=_dKg]" element
    And I should see the text "Put exact words in quotes"

Pause for a moment to marvel at the Gherkin BDD test syntax: which means I don't have to explain what the test above does; but also means that the test above is already pretty powerful (and you haven't had to write a single line of code to leverage that power!)

Run!

Wait, come back! I mean, run your new test: just run bin/behat. You should see the following output:

Feature: Navigate website.
  In order to begin working with my website
  As a site visitor
  I need to be able to navigate around the site
 
  Scenario: Access advanced search                                        # features/navigate.feature:6
    Given I am on the homepage                                            # Drupal\DrupalExtension\Context\MinkContext::iAmOnHomepage()
    When I click "Advanced search"                                        # Drupal\DrupalExtension\Context\MinkContext::assertClick()
    Then I should see "all these words:" in the "label[for=_dKg]" element # Drupal\DrupalExtension\Context\MinkContext::assertElementContainsText()
    And I should see the text "Put exact words in quotes"                 # Drupal\DrupalExtension\Context\MinkContext::assertTextVisible()
 
1 scenario (1 passed)
4 steps (4 passed)
0m0.77s (17.98Mb)

It's a kind of annotated version of your original Gherkin feature, telling you which PHP methods were invoked to correspond to (and therefore handle) each pseudo-English assertion.

You're done!

Actually, in testing, you're never done. You should write more tests for your site! Think of things your users or visitors need to do—especially bottom-line things, like logging in, donating or purchasing—and write tests for them. Then get those tests to run! Then write more tests, as you roll out new functionality. And if you're feeling particularly brave, you should write more tests before you even begin new functionality: watch the tests fail, then write the functionality to make them pass, then... actually make them pass.

You can (and should) retrofit a test suite like this to an existing project with no tests. But next time you're thinking of starting a new project, ask yourself the question: can I spare ten minutes to start writing tests from the very beginning? I think we know what the answer ought to be!

Comments

I have developed and IDE for make behaviour testing easy with Drupal, you can check it here: http://behavedrupal.com/ide.html It is opensource you can find the code here: https://github.com/UnnikrishnanBhargavakur,  Please make a look and add you feedbacks:

http://behavedrupal.com

Please delete this comment if it is not relevant here