Behaviour Driven Development

Практика розробки тестів яка базується на вимогах (опис очікуваної поведінки) і їх проходження. BDD переводить обговорення тесту з мови тестування програмних класів(units) у мову замовника (метафору). По BDD тестам можливо згенерувати документацію на розроблювану систему зрозумілу замовнику.

Порівняйте різні підходи до структурування тестів UnitTest Department testCreateObject testAddEmployee Behaviour Test Department should be able to create a new department should be able to include an employee BDD provides a “ubiquitous language” for analysis . Around this time, Eric Evans published his bestselling book Domain-Driven Design. In it, he describes the concept of modeling a system using a ubiquitous language based on the business domain, so that the business vocabulary permeates right into the codebase. Chris and I realized we were trying to define a ubiquitous language for the analysis process itself! We had a good starting point. In common use within the company there was already a story template that looked like this:

As a [X] I want [Y] so that [Z]

where Y is some feature, Z is the benefit or value of the feature, and X is the person (or role) who will benefit. Its strength is that it forces you to identify the value of delivering a story when you first define it. When there is no real business value for a story, it often comes down to something like ” . . . I want [some feature] so that [I just do, ok?].” This can make it easier to descope some of the more esoteric requirements.

From this starting point, Matts and I set about discovering what every agile tester already knows: A story’s behaviour is simply its acceptance criteria – if the system fulfills all the acceptance criteria, it’s behaving correctly; if it doesn’t, it isn’t. So we created a template to capture a story’s acceptance criteria.

The template had to be loose enough that it wouldn’t feel artificial or constraining to analysts but structured enough that we could break the story into its constituent fragments and automate them. We started describing the acceptance criteria in terms of scenarios, which took the following form:

Given some initial context (the givens), When an event occurs, then ensure some outcomes. To illustrate, let’s use the classic example of an ATM machine. One of the story cards might look like this:

Title: Customer withdraws cash As a customer, I want to withdraw cash from an ATM, so that I don’t have to wait in line at the bank.

So how do we know when we have delivered this story? There are several scenarios to consider: the account may be in credit, the account may be overdrawn but within the overdraft limit, the account may be overdrawn beyond the overdraft limit. Of course, there will be other scenarios, such as if the account is in credit but this withdrawal makes it overdrawn, or if the dispenser has insufficient cash.

Using the given-when-then template, the first two scenarios might look like this:

Scenario 1: Account is in credit Given the account is in credit - And the card is valid - And the dispenser contains cash When the customer requests cash Then ensure the account is debited - And ensure cash is dispensed - And ensure the card is returned

Notice the use of “and” to connect multiple givens or multiple outcomes in a natural way.

Scenario 2: Account is overdrawn past the overdraft limit Given the account is overdrawn - And the card is valid When the customer requests cash Then ensure a rejection message is displayed - And ensure cash is not dispensed - And ensure the card is returned

Both scenarios are based on the same event and even have some givens and outcomes in common. We want to capitalize on this by reusing givens, events, and outcomes. Acceptance criteria should be executable . The fragments of the scenario – the givens, event, and outcomes – are fine-grained enough to be represented directly in code. Having a class to represent each fragment enables us to reuse fragments in other scenarios or stories. At first, the fragments are implemented using mocks to set an account to be in credit or a card to be valid. These form the starting points for implementing behaviour. As you implement the application, the givens and outcomes are changed to use the actual classes you have implemented, so that by the time the scenario is completed, they have become proper end-to-end functional tests.

Last updated