Tuesday, October 22, 2013

Behaviour testing with PHP

What it I told you that you can write tests for your application in plain english? Not a single semicolon or brace required? Well, it is possible - and not entirely true. I'll get back to that.

Behat is a (or rather the) BDD (Behavior-driven development)  framework for PHP. You describe the behavior of the application with simple "Given - When - Then" steps and there is your test. And when you got multiple tests, you have specifications of how the application is supposed to work - all in human readable format.

An example test case

Feature: Login functionality allows login only from user with correct username/password 
    In order to use all sites features 
    As a user 
    I need to be able to log in
Scenario: User is able to log in 
    Given system has a user "BehatTester" that has password "correctpassword"
    When user logs in with user name "BehatTester" and password "correctpassword"
    Then user is redirected to "/welcome" And message "Welcome BehatTester" is shown

Is that readable (and writable) or what? People who write tests no longer have to have any programming experience.
  • Feature-statement is used to describe one feature of a program and Scenario-statement is describes one use case of that feature.
  • Suites have multiple Features that have multiple Scenarios that have multiple Given-When-Then -steps.
  • Given-statements normally change the status of the program, in the example scenario the given step would save a user "BehatTester" to system and give it password "correctpassword".
  • When-statemets simulates actions made by user (or another actor), for example form submission, opening a page etc.
  • Then-statements verify that expected things happen, in similar way that in PHPUnit uses "assert"-functions.
  • Multiple Given, When and Then -statements can be given simply with "And"

Peek under the hood

Unfortunately the scenarios are not enough to get the tests to work. And this is where comes the actual programming of tests. When a Behat-test is executed, Behat parses the scenarios and their steps and tries to find matching function from "Feature"-classes that are written in PHP. Then Behat executes those functions in the order specified in the scenario.

In order to setup and teardown the state of the system under test Behat implements hooks. They're Feature-classes methods that are marked with "@EventName" comments. A very useful hook is "@BeforeFeature" - the function marked with this tag is executed before the first step of every feature. It has a counter-part "@AfterFeature"-tag.

Behat has a very useful feature: if no matching function is found for step, then Behat prints a "code-snippet" that you can just copy+paste into your Feature-class and then implement. This speeds up the test-writing process nicely.

Behat-tests do not remove the need for Unit-tests. But they are very useful as acceptance-level tests.

I'll write a more in-depth blog about using Behat. In the meantime, if interested, do visit Behat Docs.

1 comment:

  1. Actually one doesn't have to copy+paste the code snippets.
    "behat features/ --append-to NameOfClass" will do it for you!

    This keeps getting better

    ReplyDelete