Behavior Driven Development, Acceptance Testing and Behat

This post is part of my "Continuous Integration on a Budget" series, and covers the "whats" of Behat and other tools available to implement Behavior Driven Development as part of your Continuous Integration process.

So, I have to admit -- I got inspired to go further with automated testing. At Drupal Camp Chattanooga, Johnnie Fox presented a topic in the session right before mine titled "DIY Continuous Integration: Know it. Do it. Now" where he talked about some of the CI processes that his team was adopting at Promet Source. I had a chance to chat a bit with Johnnie later that day about the topic of CI in general, and Behat in particular. I had put Behat on my list of things to familiarize myself with over the next year, and after Johnnie's presentation and our subsequent talk, Behat moved way up on the list. If you didn't have a chance to come to Chattanooga for Drupal Camp this year and would like to hear Johnnie's session, never fear, he'll be presenting at Drupal Camp Atlanta as well, next month.

So, yesterday, I played with Behat a bit. Wow.

Afterwards I started looking for more information about Behat and Drupal and Behavior Driven Development -- and found alot, which inspired me even more.

Then I started looking at integrating Behat with Jenkins and Phing -- and found, not so much. So, I thought I would collect what I did find in one place and hopefully make it easier for you, too, to integrate Behat into your Continuous Integration processes for Drupal development.

What is Behat?

In short, Behat is a testing framework written in PHP that accepts tests written in very easy to understand, english-like grammar and syntax, and executes those tests on your web application project using a variety of technical tools, including browser simulators to simulate human web browsing activities. The beauty of Behat is: you don't have to be a developer to craft those tests (because we, as developers, know that we hate spending time writing tests). You just have to understand the english-like syntax of the test language.

I know, you're thinking, "So, what is this mysterious language of which you speak?"

It's called Gherkin, and it was originally crafted for use with Cucumber, which is an acceptance testing framework written in Ruby after which Behat was modeled. Gherkin's grammar and syntax is very much modeled after the spoken word, and was heavily influenced by the User Stories component of Agile modeling, which are used to define the business requirements for a project when you use the Extreme Programming approach to project development. Writing User Stories for Agile typically involves the client as well as the project manager, so solicitation of client input in crafting those user stories is key to a well defined set of requirements. This is why it is vitally important that the language used to write those stories, which also serve as our test definitions, be easy to understand for the non-technical people involved in our projects, our clients (or "stakeholders" in Agile-speak).

Once you get a set of well-written user stories, you take those stories and, together with the client, you craft the Acceptance Tests for each of the User Stories that is going into the next iteration, or code sprint. The Acceptance Tests are written in spoken word syntax so that there is no ambiguity among the developer team and the stakeholders (the client) as to what each of the acceptance tests means.

Done right, you kill two, no three, birds with one stone -- you get a well defined set of acceptance tests, written in syntactically correct Gherkin, that

  • The client can understand and therefore accept as a good representation of their expectations
  • Can be incorporated into your scope definitions, which should be part of the contract with your client
  • Defines and writes your test cases BEFORE you write a single line of code

When you are trying to manage client expectations and keep the development costs of a project within a defined and agreed upon scope (which we all know is a challenge), this is monumental. It's difficult for the client to say "Well, that's not really what I meant" (and therefore introduce a massive amount of what we all know as "scope creep") when the definition of the user stories and the acceptance tests for those stories, which with Gherkin make up the test cases for usability that your development efforts are measured against, are written in what amounts to not much more than "plain english".

Wow.

Now you don't necessarily have to be an expert in Extreme Programming or Agile Software Development to use Behat and Gherkin, but the process behind defining the tests will naturally lead you down that path, and make adopting an Agile approach much easier.

User Story Acceptance Tests Examples and Features

In Agile-speak, a user story typically is defined with certain components:

  • A User (defined as a user role)
  • An action or occurrence
  • A benefit

User stories are typically written in the style "As a [user role], I want to [perform an action] so that I can [gain a benefit]", like so :

As a user who forgot their password, I want to reset my password so that I log in.

For Behat, a test is typically defined in Gherkin as a Feature. A Feature (which is a component of the project) is composed of Scenarios (or specific use cases) that are defined with the following components:

  • A User with a need
  • An Action to be performed
  • An Outcome

and are written in the following style:

Feature: [Overall description of the purpose of this component of the project]
  Scenario: [Description of an acceptance test case]
    Given [I am a user with a specific need]
    When [I perform a certain action]
    Then [I get a certain outcome]

A typical Feature written in Gherkin with a defined set of Acceptance Tests will look something like this:

Feature: User Password management
  Scenario: User Forgot password
    Given I am a user who clicks on the password reset tab
    When I provide my username
    And I click the "Request Password Reset" button
    Then an email with a password reset link is sent to me
  Scenario: User Receives Password Reset Email
    Given I am a user who received a password reset email
    When I click on the emailed password reset link
    Then I am shown a password reset form
  Scenario: User Completes Password Reset Form
    Given I am a user who fills out a password reset form
    When I click the Change Password Button
    Then my new password is saved
  Scenario: User Wants to Change Password
    Given I am an authenticated user with the username "typicalUser"
    When I want to change my password
    Then a new password form is presented
  Scenario: User Completes New Password Form
    Given I am an authenticated user who fills out a new password form
    When I click the Save Password Button
    Then my new password is saved

That's it. It's that simple. The only "required" components are the keywords "Feature:", "Scenario:", "Given", "When", and "Then". Syntactically it doesn't get any simpler than that. Even an elementary school child can write a syntactically correct Scenario and compose a valid Feature in Gherkin.

In my next post, I'll cover installing Behat in your project code so that you can start using Acceptance Testing in your coding methodologies.