The PHP tool Behat has been drawing attention to itself for some time now. Within the PHP community it has caused a growing awareness for the topic Behavior Driven Development (BDD). Even though there were similar BDD frameworks to Behat for other programming languages before, like JBehave and particularly Cucumber, it was not until Behat that BDD came into the focus of web developers – at least as a term. Especially in the case of web applications, which are usually very “UI-oriented”, BDD is useful for creating automated acceptance tests, which go beyond Unit Tests and Integration Tests. But is practicing BDD actually equivalent to creating automated acceptance tests? And is BDD a practice, a method, or just an abstract school of thought? How does Behat fit into the big picture?
Here at YMC, we believe there is much confusion around these questions. Hence we want to provide some clarification by first explaining the concept behind the tool – as we follow the principle that a tool should not be employed without a well-defined purpose in mind.
The “code-focused” developers thinking this blog post appears too abstract can rest assured we will concretely deal with Behat (code) in a subsequent blog post.
Automated acceptance tests – from a pragmatic point of view
Mink is the tool of choice for automating PHP web application acceptance tests – avoiding the laborious process of conducting tests manually. This framework for “Web Acceptance Testing” is part of the Behat framework. Regardless of whether it is employed independently or together with Behat, you can simulate interactions between the user and the browser with it. For that, Mink utilizes testing tools like Selenium, Sahi or Goutte and it abstracts the APIs of all these tools in the form of a single generic API. Thus, you can implement acceptance tests almost independently from a specific tool, which is particularly beneficial for the longevity of the tests. But Mink was not an integral part of a BDD framework from the beginning without reason. By just looking at the technical fact of the separation between Behat and Mink, you see that BDD deals with more than just implementing automated acceptance tests. For that alone, Mink in combination with PHPUnit would be entirely sufficient.
The unfortunate birth of BDD
BDD was presented as a continuation of Test Driven Development (TDD) by Dan North in 2003. He introduced syntactical conventions for Unit Tests at first: The names of the test methods should each consist of an entire sentence and the verb “test” should be amended by the auxiliary verb “should”. While the method
testFindsCustomerById() opposed to, for example,
testCustomerById() is doubtlessly more understandable, Dan North’s original intention behind the little word “should” is harder to grasp. Indeed
testShouldFindCustomerById() does not appear to be more meaningful than
testFindsCustomerById() at first sight.
Dan North’s intention behind “should” opposed to “test” was of rather more subtle nature: Focussing on the awareness of the fact that TDD does not deal with the development of automated tests for the sake of it (i.e. having as much code coverage as possible), but ensures a certain behavior of a software unit. In most cases that should also retroactively have an effect on the tested unit: Through appropriate refactoring, it subsequently complies with common principles of object-oriented design, such as the Single Responsibility Principle. That quickly led to the effect that BDD was perceived as “TDD done right“. As Dan North himself found later, this simplification together with the somehow meticulous aversion to the word “test” was not fortunate for the first hours of BDD: BDD was at first perceived as a mere TDD practice and not as that for what is was supposed to actually be…
BDD as an agile method
Moving away from the initial focus on Unit Tests, BDD can also be regarded as an agile method (and not just practice) – and today more than ever, thanks to tools such as Cucumber and Behat. From the methodical point of view, the essence of BDD is still the behavior of a piece of software – but now approached in somewhat different way: The question what to test comes more to the fore. Therefore the behavior is considered explicitly from the perspective of the user now and the piece of software does not necessarily have to be a self-contained unit anymore. In the case of the so-called scenario-oriented variant of BDD (“StoryBDD”), that Behat relies on, the behavior is described in the form of scenarios. Ideally, a user story serves as a basis: To complement or substitute acceptance criteria you write scenarios in a domain-specific language (DSL). This DSL basically consists of the three keywords
Then, which each prefixed a step that is expressed in the form of “prose”. A sequence of such steps generates a scenario that has a semantical structure:
Given a precondition
When an event occurred
Then an outcome is achieved
Apart from the predetermined keywords, it is supposed that the prose part of the scenario is written in the “language of the customer” (and not that of the developer). A classical example that illustrates scenario writing very well is the ATM user story by Dan North, with which he introduced the concept of BDD back then:
As an Account Holder I want to withdraw cash from an ATM so that I can get money when the bank is closed
An obvious acceptance criteria is that cash can be withdrawn if the bank customer is liquid and if the ATM is able to dispense the appropriate amount of cash. As a scenario Dan North describes it in the following way:
Given the account balance is \$100
And the card is valid
And the machine contains enough money
When the Account Holder requests \$20
Then the ATM should dispense \$20
And the account balance should be \$80
And the card should be returned
Automated acceptance tests – created through BDD
Even though we practically oriented agilists still have automated acceptance tests as a goal in mind, they are according to BDD philosophy, rather artifacts that actually “come into existence” along the way. When practicing BDD, the question what to test should actually cause a better understanding of the software requirements (which in detail often are not known by the customer as well). Dan North clarified that concisely in a forum discussion:
“BDD is about understanding the customer’s need [...] (and being able to prove that with an evolving suite of acceptance tests)”
This aspect is interesting when justifying the alleged extra cost for BDD compared to “pure” testing practices like, for example, the test-first practice from XP. In the best case, BDD does not only cause you to implement something correctly and that you ensure this by automated tests, but also that you implement the right thing (and that you ensure this by acceptance tests). In the broader sense you can regard this approach of BDD as even an agile variant of requirements elicitation. It is agile alone because of the necessity of a close collaboration with the customer (and other project stakeholders) in order to write scenarios, as a consequence, at least one of the four agile values is directly put into practice.
Of course, a formalization of the scenarios in a DSL is not needed for the sole purpose of requirements elicitation. And to put the scenarios down on paper in “spoken language” together with the customer as a start, instead of prematurely concern oneself (and the customer) with “grammar”, is certainly an approach that leads us faster to the goal. Though in the end, the scenarios written in the DSL constitute executable specification artifacts: The “Givens”, “Whens” and “Thens” provide a structure, that facilitates parsing and interpreting – i.e. “executing” – the description by an appropriate tool. While the parsing is done by Behat, the interpreting is the actual intricacy in the case of StoryBDD. At least for the developer, who has to ensure by a suitable implementation that all preconditions are met, that all user interactions are (correctly) simulated, and that the expected outcomes are achieved.
Finally we can conclude that BDD is more than just creating automated acceptance tests. In the ideal case BDD is practiced as a method as part of an agile development process, where tests might be desired or demanded, but where they are not at the fore. Before the automated tests, it deals with eliciting the right requirements and implementing them correctly. Approached in any other way, BDD rather becomes a process overhead. In this case, employing Behat as a tool does not make sense anymore – for that Mink alone is suitable.