BDD & Behat

BDD is an amazing way to test software. Behat is a PHP BDD framework that works well with Laravel.

History of testing

Testing has always been a part of software development, but only recently has it been formalised into a work methodology. TDD(test driven development) dictates that the developer writes the tests first then the actual functionality. TDD suffers from two issues: 1.) It’s very difficult to get right. 2.) It’s very developer centric, developers usually only test the happy case scenario. TDD for functional testing is difficult because it’s very code orientated. A skilled QA(quality assurance tester) has a different skill set from a developer and they should feel free to strengthen those core skills instead of developing programming skills.

Why BDD?

BDD was created out of combining TDD, Domain Driven Design and object orientated programming. It focuses on testing the core functionality of the product rather than testing every single part and providing a means for both technical and business interests to be represented in the tests.

What I like the most about BDD is a QA does not have to write any code to write functioning(not just functional) tests. They rely on a set of pre-written pieces of code that are bound to plain English sentences. The sentences are strung together into a paragraph. The paragraph represents a test. Using this approach makes it clear what the test is actually for, the test is self documenting. The net result is developers can concentrate on writing code and QAs can concentrate on writing tests.

Behat

Behat is a BDD framework for PHP that has excellent integration with Laravel. It’s installed via composer like any other modern PHP package and has an executable in the *vendor/bin* folder. To add behat to the project put the following in the require-dev section in the composer file:

“behat/behat”: “^3.0”,
“behat/mink”: “^1.6”,
“behat/mink-extension”: “^2.0”,
“laracasts/behat-laravel-extension”: “^1.0”

It’s necessary to install the mink packages for browser(functional) testing. Mink is an extension package for Behat to allow for browser or web testing. Once installed execute

vendor/bin/behat --init

to create the features directory where the behat files are stored.

In the features directory create a “webpages.feature” and copy in the following

Feature:
  In order to prove that Behat works as intended
  We want to test the home page for a phrase

  Scenario: Root Test
    When I am on the homepage

Create this file in the project directory: “behat.yml”, copy in the following

default:
    extensions:
        Laracasts\Behat:
             env_path: .env
        Behat\MinkExtension:
            default_session: laravel
            base_url: http://docrepo.lh
            laravel: ~

Alter the FeatureContext class definition to look like that following

class FeatureContext extends MinkContext implements Context, SnippetAcceptingContext

Run

vendor/bin/behat —dl

to get a list of command that you can use when creating new tests.

When you are done creating the tests, run the following

./vendor/bin/behat features/webpages.feature

to execute the tests, you should see the following output

Feature:
  In order to prove that Behat works as intended
  We want to test the home page for a phrase

  Scenario: Root Test         # features/webpages.feature:5
    When I am on the homepage # FeatureContext::iAmOnHomepage()

1 scenario (1 passed)
1 step (1 passed)
0m0.14s (29.27Mb)

Features file

The feature file can be called anything, I just used webpages as a way to specify what it tests. The feature file uses the gherkin language which defines a set of keywords to differentiate areas and actions. Gherkin was designed especially for describing system behaviour. It gives us the ability to remove logic from behaviour tests.

  • Feature Some high level description of the functionality, this ties in with the functional specification.
  • Scenario This is a use case for how a user will use the functionality.
  • Given This sets up the precondition for the test, assigns values to variables, …
  • When Would be a user action, ex. a user presses a button.
  • Then Tests an assertion, in other words that the test failed or passed.

Code

In the FeatureContext PHP file create the following method

/**
 * @When I click on photography
 */
public function IClickOnPhotography()
{
    $this->getSession()->getPage()->find(“css”, “[href=‘/photography’]”)->click();
}

and add the following under the scenario

And I click on photography

Add the following to the FeatureContext file

/**
 * @Then I am on the photography page
 */
public function IAmOnThePhotographyPage()
{
    if ($this->getSession()->getPage()->has('css', '.list-unstyled.photography-photo-list') == null) {
        throw new Exception(
            'We are not on the photography page'
        );
    }
}

And this in the scenario

Then I am on the photography page

When you run the test you should see

Feature:
  In order to prove that Behat works as intended
  We want to test the home page for a phrase

  Scenario: Root Test                 # features/webpages.feature:5
    When I am on the homepage         # FeatureContext::iAmOnHomepage()
    And I click on photography        # FeatureContext::IClickOnPhotography()
    Then I am on the photography page # FeatureContext::IAmOnThePhotographyPage()

1 scenario (1 passed)
3 steps (3 passed)
0m0.14s (30.37Mb)

Selenium

Selenium is a java service that can control the browser for proper functional tests in a production environment, similar to what a user would experience in the real world. It’s a jar file that can be executed from the command line via

java -jar selenium-standalone-*jar

Behat has the ability to talk to selenium on our behalf to run the tests. To configure selenium testing we have to add the mink selenium driver to the require-dev section.

“behat/mink-selenium2-driver”: “*”

and change the content of the behat.yml file to

default:
    extensions:
        Behat\MinkExtension:
            base_url: http://www.fritsstegmann.co.za/
            default_session: selenium2
            selenium2: ~

Execute the test with

./vendor/bin/behat features/webpages.feature

You should see a browser popup and complete the described actions.

Conclusion

I hope you can see the potential for creating quick and flexible tests and the potential for separating the testing and development of a software products.

Leave a Reply

Your email address will not be published. Required fields are marked *