Enabling Automated BDD Testing In Drupal With Behat

Karl Kedrovsky

Solutions Architect at VML

Drupal developer since 2005

Kansas City Drupal Users Group

What We'll See Today

  • A (poor) definition of BDD
  • How to write the tests
  • Tools - Both Drupal and non Drupal
  • Some approaches to integrating Behat into your projects

Definition

A communication and collaboration framework for developers, QA and non-technical or business participants in a software project

-- Wikipedia

Definition (In Practice)

Developing an application (as opposed to a unit of code) by:

  • Describing the behavior of a feature of our application
  • Implementing the feature
  • Validating the behavior of the application using the description
  • Lather, rinse, repeat

Describing The Behavior

Gherkin

Gherkin is a declarative, business readable, domain specific language created especially for behavior descriptions.

Gherkin

homepage.feature


Feature: Home Page
Tests the home page

Scenario: View home page
  Given I am on "/"
  Then I should see "Welcome to behat"
              

  • Given - Precondition
  • When - User action
  • Then - Testable outcome

Puzzle Pieces

  • Behat - BDD framework written in PHP. Not specific to the web.
  • Mink - Test framework for web applications written in PHP.
  • Drupal Extension - Behat/Mink extension that provides Drupal specific behavior.
  • Behat Runner - Drupal module that makes it easy to discover and run Behat tests.

Tooling

Using Behat as a standalone tool

Behat Runner Drupal module

Standalone Behat

Run:


mkdir drupalcorn_behat
              

composer.json


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

Run:


composer install
              

Standalone Behat


drupalcorn_behat
├── behat.yml
├── bin
├── composer.json
├── composer.lock
└── vendor
              

Demo

Standalone Behat

behat.yml


default:
  paths:
    features: 'features'
  extensions:
    Behat\MinkExtension\Extension:
      goutte: ~
      selenium2: ~
      base_url: http://behat/
    Drupal\DrupalExtension\Extension:
      blackbox: ~
              

Standalone Behat

Run:


mkdir features
              

features/homepage.features


Feature: Home Page
  Tests the home page

  Scenario: View home page
    Given I am on "/"
    Then I should see "Welcome to behat"
              

Run:


./bin/behat
              

Demo

Using Behat Runner

Installing Behat Runner

YOU HAVE TO USE DRUSH!

Edit settings.php and set $base_url


drush en -y behatrunner
drush brm
drush bls
drush brun
              

Demo

Adding Tests With Behat Runner

Custom Modules

New module just for testing - Behat Drupalcorn

Custom Modules

behat_drupalcorn.info


name = Behat Drupalcorn
description = Sample module for Drupalcorn Behat talk
core = 7.x

dependencies[] = behatrunner
              

Custom Modules

behat_drupalcorn.module


<?php

/**
 * Implements hook_behat_info()
 */
function behat_drupalcorn_behat_info() {
  $info = array(
    'paths' => array(
      'features' => 'features',
    ),
  );

  return $info;
}
              

Custom Modules

features/homepage.feauture


Feature: Home Page
  Tests the home page

  Scenario: View home page
    Given I am on "/"
    Then I should see "Welcome to behat"
              

Demo

Features

Features

Setup - Blog feature

Features

behat_talk_blog.behat_tests.inc:


<?php

/**
 * Implements hook_behat_info()
 */
function behat_talk_blog_behat_info() {
  $info = array(
    'paths' => array(
      'features' => 'features',
    ),
  );

  return $info;
}
              

Features

Add this line to the end of behat_talk_blog.module:


include_once 'behat_talk_blog.behat_tests.inc';
              

Features

features/blog.feature:


Feature: Blog
  Tests the blog feature

  Scenario: View blog page
    Given I am on the homepage
    When I click "Blog"
    Then I should see "The Really Cool Blog"
              

Demo

Drupal Extension

Blackbox Driver

Assumes no privileged access to the site

Server can be local or remote

Region Maps

  • I should see "About Us" in the "footer" region

Check for Drupal errors or messages

Drush Driver

Allows tests to be run as logged in users with specific roles

Server can be local or remote

Drupal API Driver

Allows tests to be run as logged in users with specific roles

Lets you create nodes, vocabularies, and terms in the test specs

Fastest of the three drivers

Must be run locally

API Example


  @api
  Scenario: Create blog post
    Given "blog_post" nodes:
    | title      | body                |
    | First Post | Sample body content |
    When I go to "blog"
    Then I should see "First Post"
              

The drush and api drivers require the "@api" tag so the system knows to bootstrap Drupal

Demo

Driver Specification

sites/default/files/behatrunner/behat.xml


default:
  extensions:
    Behat\MinkExtension\Extension:
      goutte: null
      default_session: goutte
      javascript_session: selenium2
      selenium2:
        wd_host: 'http://127.0.0.1:4444/wd/hub'
      base_url: 'http://behat'
    Drupal\DrupalExtension\Extension:
      blackbox: null
      drush:
        alias: '@self'
      api_driver: drupal
      drupal:
        drupal_root: /var/www/behat
      region_map:
        footer: #footer
              

Custom Subcontexts

Lets you write reusable step definitions for your modules

Mink Drivers

Goutte

  • Pure PHP - No external dependencies
  • Very fast
  • No javascript support

Zombie.js

  • Requires Node.js
  • Supports javascript

PhantomJS

  • Headless WebKit browser (Goutte and Zombie.js use a custom DOM implementation)

Selenium Server

  • Requires java and a running Selenium server
  • Mature and robust
  • Common tool for automated browser tests

Shameless Thievery

http://www.previousnext.com.au/blog/using-mink-web-testing

Getting Started

Just Set It Up

Install Behat standalone (with the Drupal Extension) or the Behat Runner module

Use the Goutte Mink driver

Create a single feature file with the simplest scenario you can think of

Write Test For Bugs

Any time you get a bug report write the test first then fix it

Automate It

Integrate the test with Jenkins/whatever to run when code is checked in

Inculcate It

Make test reviews part of your code/build reviews

When bugs are maked as fixed ensure they have a test before they're closed

Reward/shame team member create (or fail to create) tests

Resources

Behat/Mink - http://behat.org

Gherkin - http://docs.behat.org/guides/1.gherkin.html

Drupal Extension - https://www.drupal.org/project/drupalextension

Drupal Extension Docs - http://dspeak.com/drupalextension

Behat Runner - https://www.drupal.org/project/behatrunner

My Github - https://github.com/karlkedrovsky

  • vagrant-starter

Questions?

Thank You!

Email - karl@kedrovsky.com or kkedrovsky@vml.com

Twitter - @karlkedrovsky

Drupal.org - https://www.drupal.org/u/karlkedrovsky