ビヘイビア駆動開発 (BDD)

ビヘイビア駆動開発 (振舞駆動開発; behavior driven development; BDD)とは、プログラム開発手法の一種で、テスト駆動開発から派生した物である。

テスト駆動開発で記述されるテストケースは、作成したプログラムの動作が正しいかどうかを検証するために行う「テスト」である。テストであるという点は同一であるが、加えて、これから作成しようとするプログラムに期待される「振る舞い」や「制約条件」、つまり「要求仕様」に近い形で、自然言語を併記しながらテストコードを記述する。テストフレームワークのメソッド名も自然言語(英語など)に近い形をとっている。

テストコードの可読性があがる上、テストコードが要求仕様となりうる。要求仕様からテストコードを起こす際も、スムーズにコードに移行しやすい。

BDDではスペック(仕様)とテストは限りなく近い物である。従って、テスト駆動開発における「テストファースト」は、BDDにおいては「スペックファースト」となり、スペックを作ってから実装するという、より自然な形でのプログラム製作を実現している。

いくつかのテストフレームワークは、

アプリケーションの振る舞いを記述するストーリーフレームワーク
オブジェクトの振る舞いを記述するスペックフレームワーク
の2種類を含む。

BDD Framework

今はCucumberが一番メインで使われていると思うのでそれを使えばいいと思います。

適当にインストールして使ってみてください。

Rubyの場合は、普通にRSpecでも良いみたいです。

https://relishapp.com/rspec

BehaviourDrivenDevelopment

Behaviour-Driven Development (BDD) is an evolution in the thinking behind TestDrivenDevelopment and AcceptanceTestDrivenPlanning.

It brings together strands from TestDrivenDevelopment and DomainDrivenDesign into an integrated whole, making the relationship between these two powerful approaches to software development more evident.

It aims to help focus development on the delivery of prioritised, verifiable business value by providing a common vocabulary (also referred to as a UbiquitousLanguage) that spans the divide between Business and Technology.

It presents a framework of activity based on three core principles:

Business and Technology should refer to the same system in the same way – ItsAllBehaviour

Any system should have an identified, verifiable value to the business – WheresTheBusinessValue

Up-front analysis, design and planning all have a diminishing return – EnoughIsEnough

BDD relies on the use of a very specific (and small) vocabulary to minimise miscommunication and to ensure that everyone – the business, developers, testers, analysts and managers – are not only on the same page but using the same words.

For people familiar with the concept of DomainDrivenDesign, you could consider BDD to be a UbiquitousLanguage for software development.

It must be stressed that BDD is a rephrasing of existing good practice, it is not a radically new departure. Its aim is to bring together existing, well-established techniques under a common banner and with a consistent and unambiguous terminology. BDD is very much focused on “Getting the words right” and this focus is intended to produce a vocabulary that is accurate, accessible, descriptive and consistent.

In fact “Getting the words right” was the starting point for the development of BDD, and is still very much at its core, but the power of getting the words right has led to some insights and extrapolations that have helped us to better understand our approach and to extend it.

Feel free to edit anything you find to make it clearer or to add your opinion (and sign with YourName if you like).

Interesting starting points:

Introduction : A brief overview

Test Driven Development (TDD) has established itself as a useful–and at its best, profound–improvement in the software development process. It delivers a variety of benefits to its practitioners; some of them are related to testing, but the most important benefits are not.

Experienced practitioners, particularly those that have been involved in helping other developers learn the practice, note a life-cycle to TDD’s learning and adoption:

  1. The developer starts writing unit tests around their code using a test framework like JUnit or NUnit.
  2. As the body of tests increases the developer begins to enjoy a strongly increased sense of confidence in their work.
  3. At some point the developer has the insight (or is shown) that writing the tests before writing the code, helps them to focus on writing only the code that they need.
  4. The developer also notices that when they return to some code that they haven’t seen for a while, the tests serve to document how the code works.
  5. A point of revelation occurs when the developer realises that writing tests in this way helps them to “discover” the API to their code. TDD has now become a design process.
  6. Expertise in TDD begins to dawn at the point where the developer realizes that TDD is about defining behaviour rather than testing.
  7. Behaviour is about the interactions between components of the system and so the use of mocking is fundamental to advanced TDD.

We have observed this progression in many developers, but unfortunately while most, with a little help, find their way to step 4, many miss the big wins found at steps 5, 6 and 7.

We started wondering why this was, and wondering what we could do to help people get to the good stuff more quickly. Looking closely at this evolution in understanding, while step 1 may be considered to be related to testing, the rest really are not. For the remainder of the steps in this process, the test aspect is very much a secondary concern. The issue at the heart of this learning process is the behaviour of the system. Developers gain confidence in the systems they build when the behaviour of that system is confirmed.

By writing tests in advance of code, the developer defines the behavioural intent of the system that they are developing. Tests that document the behavioural intent of the system are most valuable as documentation of that system. By specifying the behaviour of the code in tests, developers are able to best consider the interface from the perspective of the consumer of the service rather than as the producer – thinking more abstractly about the nature of the solution and so hiding technical detail.

This focus on behaviour ahead of testing is a focus on the real value in TDD, and in our experience is the mark of the genuinely experienced TDD practitioner.

It is not too surprising that it takes apprentice TDD practitioners a while to realize that TDD is not about testing when all of the nomenclature surrounding it is described in terms of testing.

The aim of Behaviour Driven Development (BDD) is to address this shortcoming. By using terminology focused on the behavioural aspects of the system rather than testing, BDD attempts to help direct developers towards a focus on the real value to be found in TDD at its most successful.

BDD aims to bridge the gap between the differing views of computer systems held by Business users and Technologists. It is deeply rooted in the success of TDD and is influenced by ideas like Domain Driven Design. Its focus is on minimizing the hurdles between specification, design, implementation and confirmation of the behaviour of a system. Thus enabling the incremental delivery of business systems, and in particular in allowing teams new to agile development to quickly get up to speed using these extremely productive techniques.

BDD relies on the use of a very specific (and small) vocabulary to minimize miscommunication and to ensure that everyone – the business, developers, testers, analysts and managers – are not only on the same page but using the same words. It must be stressed that BDD is a rephrasing of existing good practice, it is not a radically new departure. Its aim is to bring together existing, well-established techniques under a common banner and with a consistent and unambiguous terminology. In fact, “Getting the Words Right” was the starting point for the development of BDD, and is still very much at its core. “Getting the Words Right” is intended to produce a vocabulary that is accurate, accessible, descriptive and consistent.

The BDDProcess : A description of a development process using BDD

The BDD process looks like this:

A SubjectMatterExpert (typically a business user) works with a BusinessAnalyst to identify a business requirement. This is expressed as a story using the following template:

As a Role

I request a Feature

To gain a Benefit

The speaker, who holds the Role, is the person who will gain the Benefit from the requested Feature.

This can also be paraphrased variously as …

I want to achieve a specific Goal, and as a Role I should be able to accomplish this by performing Functionality.

A Role invokes Feature to cause a Benefit

Related Topics
StructureOfaProject, ProcessRationale, StructureOfAnIteration, FindingRequirements,

FindingStories, DevelopmentEstimates, NextMostImportantStory, BehaviourDrivenCode,

ShowAndTellSession

BehaviourDrivenAnalysis : How do we approach analysis for BDD?

We explore how software can help address a business problem by asking, what are known as, PowerfulQuestions. This technique is intended to develop insight, and allows us to explore new avenues and better understand existing ones.

We approach BehaviourDrivenAnalysis in a structured way to minimise the risk of missing anything useful. Use Cases are a useful tool for establishing the boundaries of a system, in the sense of understanding what the system is (and more importantly is not) responsible for. A Use Case in this context describes an Actor (someone or something in a Role) interacting with some exposed interface to our system.

The important distinction between behaviour-driven Use Cases and the traditional Rational version is that the Use Case must specify the business value of the interaction. At this level the description of the value can be quite broad or vague, but it must be there (because we will drill down into it later). We use Use Cases as a launching point to understand the value at a finer level of granularity, which in turn allows us to prioritise the delivery of functionality as we go along. We talk about prioritising later on, when we discuss BehaviourDrivenPlanning.

BehaviourDrivenProgramming : What changes do we make to our approach to programming?

BehaviourDrivenProgramming is a refinement and reframing of TestDrivenDevelopment that, amongst other things, helps speed the effective introduction of newcomers to the techniques and benefits of this approach to development.

By the time developers get to [:TDDAdoptionProfile:the stage where they are writing tests before writing the code], the tests are usually mainly state-based – asserting values at the end of the test method.

These test are often more like integration tests, hitting a database or requiring complex setup of state for each test, rather than the speedy unit tests we hope for. This type of testing tends to result in very brittle tests, where test implementation is tightly coupled to the implementation of the code being tested.

This is an extremely common failure mode for codebases on Agile projects, where the tests become increasingly a constraint on change rather than enabling it because refactoring the code requires altering the tightly coupled tests and so becomes both time-consuming and error-prone.

An interesting aside in favour of agile development techniques in general and TDD in particular is that even in this state the code is often much more robust and a much better functional fit than code developed under more traditional methods based on large-scale up-front design.

Advanced TDD practitioners realise that the tests are really about interactions between objects. These experts use mock objects [ref Mackinnon et al] to set and verify expectations about how objects will interact. The state becomes a side-issue. TDD code written in this way is characterized by narrow, well-named interfaces describing the roles objects play for one another. [ref Rebecca Wirfs-Brock].

Behaviour-Driven Programming jumps straight in to the interactions-and-roles stage, encouraging developers to think of the behaviour of the component that they are developing, and of the roles and responsibilities of the other objects it interacts with.

Each “test method” is called a “behaviour” and takes the form of a sentence saying what the object should do.

This is best illustrated by example so check BehaviourDrivenProgrammingExample

RecentChanges: rss feed for new or updated content.

More DescriptionsOfBDD : other ways of describing the cat-skinning process

DanNorth has written an article describing how BDD evolved.

INTRODUCING BDD
History: This article first appeared in Better Software magazine in March 2006. It has been translated into Japanese by Yukei Wachi, Korean by HongJoo Lee, Italian by Arialdo Martini and French by Philippe Poumaroux and most recently into Spanish by Oscar Zárate, Turkish by Selim Öber and Russian.

I had a problem. While using and teaching agile practices like test-driven development (TDD) on projects in different environments, I kept coming across the same confusion and misunderstandings. Programmers wanted to know where to start, what to test and what not to test, how much to test in one go, what to call their tests, and how to understand why a test fails.

The deeper I got into TDD, the more I felt that my own journey had been less of a wax-on, wax-off process of gradual mastery than a series of blind alleys. I remember thinking “If only someone had told me that!” far more often than I thought “Wow, a door has opened.” I decided it must be possible to present TDD in a way that gets straight to the good stuff and avoids all the pitfalls.

My response is behaviour-driven development (BDD). It has evolved out of established agile practices and is designed to make them more accessible and effective for teams new to agile software delivery. Over time, BDD has grown to encompass the wider picture of agile analysis and automated acceptance testing.

Test method names should be sentences
My first “Aha!” moment occurred as I was being shown a deceptively simple utility called agiledox, written by my colleague, Chris Stevenson. It takes a JUnit test class and prints out the method names as plain sentences, so a test case that looks like this:

public class CustomerLookupTest extends TestCase {
    testFindsCustomerById() {
        ...
    }
    testFailsForDuplicateCustomers() {
        ...
    }
    ...
}

renders something like this:

CustomerLookup
– finds customer by id
– fails for duplicate customers
– …
The word “test” is stripped from both the class name and the method names, and the camel-case method name is converted into regular text. That’s all it does, but its effect is amazing.

Developers discovered it could do at least some of their documentation for them, so they started to write test methods that were real sentences. What’s more, they found that when they wrote the method name in the language of the business domain,the generated documents made sense to business users, analysts, and testers.

A simple sentence template keeps test methods focused
Then I came across the convention of starting test method names with the word “should.” This sentence template – The class should do something – means you can only define a test for the current class. This keeps you focused. If you find yourself writing a test whose name doesn’t fit this template, it suggests the behaviour may belong elsewhere.

For instance, I was writing a class that validates input from a screen. Most of the fields are regular client details – forename, surname, etc. – but then there is a field for date of birth and one for age. I started writing a ClientDetailsValidatorTest with methods like testShouldFailForMissingSurname and testShouldFailForMissingTitle.

Then I got into calculating the age and entered a world of fiddly business rules: What if the age and date of birth are both provided but don’t agree? What if the birthday is today? How do I calculate age if I only have a date of birth? I was writing increasingly cumbersome test method names to describe this behaviour, so I considered handing it off to something else. This led me to introduce a new class I called AgeCalculator, with its own AgeCalculatorTest. All the age calculation behaviour moved into the calculator, so the validator needed only one test around the age calculation to ensure it interacted properly with the calculator.

If a class is doing more than one thing, I usually take it as an indication that I should introduce other classes to do some of the work. I define the new service as an interface describing what it does, and I pass this service in through the class’s constructor:

public class ClientDetailsValidator {

    private final AgeCalculator ageCalc;

    public ClientDetailsValidator(AgeCalculator ageCalc) {
        this.ageCalc = ageCalc;
    }
}

This style of wiring objects together, known as dependency injection, is especially useful in conjunction with mocks.

An expressive test name is helpful when a test fails
After a while, I found that if I was changing code and caused a test to fail, I could look at the test method name and identify the intended behaviour of the code. Typically one of three things had happened:

I had introduced a bug. Bad me. Solution: Fix the bug.
The intended behaviour was still relevant but had moved elsewhere. Solution: Move the test and maybe change it.
The behaviour was no longer correct – the premise of the system had changed. Solution: Delete the test.
The latter is likely to happen on agile projects as your understanding evolves. Unfortunately, novice TDDers have an innate fear of deleting tests, as though it somehow reduces the quality of their code.

A more subtle aspect of the word should becomes apparent when compared with the more formal alternatives of will or shall. Should implicitly allows you to challenge the premise of the test: “Should it? Really?” This makes it easier to decide whether a test is failing due to a bug you have introduced or simply because your previous assumptions about the system’s behaviour are now incorrect.

“Behaviour” is a more useful word than “test”
Now I had a tool – agiledox – to remove the word “test” and a template for each test method name. It suddenly occurred to me that people’s misunderstandings about TDD almost always came back to the word “test”.

That’s not to say that testing isn’t intrinsic to TDD – the resulting set of methods is an effective way of ensuring your code works. However, if the methods do not comprehensively describe the behaviour of your system, then they are lulling you into a false sense of security.

I started using the word “behaviour” in place of “test” in my dealings with TDD and found that not only did it seem to fit but also that a whole category of coaching questions magically dissolved. I now had answers to some of those TDD questions. What to call your test is easy – it’s a sentence describing the next behaviour in which you are interested. How much to test becomes moot – you can only describe so much behaviour in a single sentence. When a test fails, simply work through the process described above – either you introduced a bug, the behaviour moved, or the test is no longer relevant.

I found the shift from thinking in tests to thinking in behaviour so profound that I started to refer to TDD as BDD, or behaviour- driven development.

JBehave emphasizes behaviour over testing
At the end of 2003, I decided it was time to put my money – or at least my time – where my mouth was. I started writing a replacement for JUnit called JBehave, which removed any reference to testing and replaced it with a vocabulary built around verifying behaviour. I did this to see how such a framework would evolve if I adhered strictly to my new behaviour-driven mantras. I also thought it would be a valuable teaching tool for introducing TDD and BDD without the distractions of the test-based vocabulary.

To define the behaviour for a hypothetical CustomerLookup class, I would write a behaviour class called, for example, CustomerLookupBehaviour. It would contain methods that started with the word “should.” The behaviour runner would instantiate the behaviour class and invoke each of the behaviour methods in turn, as JUnit does with its tests. It would report progress as it went and print a summary at the end.

My first milestone was to make JBehave self-verifying. I only added behaviour that would enable it to run itself. I was able to migrate all the JUnit tests to JBehave behaviours and get the same immediate feedback as with JUnit.

Determine the next most important behaviour
I then discovered the concept of business value. Of course, I had always been aware that I wrote software for a reason, but I had never really thought about the value of the code I was writing right now. Another colleague, business analyst Chris Matts, set me thinking about business value in the context of behaviour-driven development.

Given that I had the target in mind of making JBehave self- hosting, I found that a really useful way to stay focused was to ask: What’s the next most important thing the system doesn’t do?

This question requires you to identify the value of the features you haven’t yet implemented and to prioritize them. It also helps you formulate the behaviour method name: The system doesn’t do X (where X is some meaningful behaviour), and X is important, which means it should do X; so your next behaviour method is simply:

public void shouldDoX() {
    // ...
}

Now I had an answer to another TDD question, namely where to start.

Requirements are behaviour,too
At this point, I had a framework that helped me understand – and more importantly, explain – how TDD works and an approach that avoided all the pitfalls I had encountered.

Toward the end of 2004, while I was describing my new found, behaviour-based vocabulary to Matts, he said, “But that’s just like analysis.” There was a long pause while we processed this, and then we decided to apply all of this behaviour- driven thinking to defining requirements. If we could develop a consistent vocabulary for analysts, testers, developers, and the business, then we would be well on the way to eliminating some of the ambiguity and miscommunication that occur when technical people talk to business people.

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. JBehave defines an object model that enables us to directly map the scenario fragments to Java classes.

You write a class representing each given:

public class AccountIsInCredit implements Given {
    public void setup(World world) {
        ...
    }
}
public class CardIsValid implements Given {
    public void setup(World world) {
        ...
    }
}

and one for the event:

public class CustomerRequestsCash implements Event {
    public void occurIn(World world) {
        ...
    }
}

and so on for the outcomes. JBehave then wires these all together and executes them. It creates a “world,” which is just somewhere to store your objects, and passes it to each of the givens in turn so they can populate the world with known state. JBehave then tells the event to “occur in” the world, which carries out the actual behaviour of the scenario. Finally it passes control to any outcomes we have defined for the story.

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.

The present and future of BDD
After a brief hiatus, JBehave is back under active development. The core is fairly complete and robust. The next step is integration with popular Java IDEs like IntelliJ IDEA and Eclipse.

Dave Astels has been actively promoting BDD. His weblog and various published articles have provoked a flurry of activity, most notably the rspec project to produce a BDD framework in the Ruby language. I have started work on rbehave, which will be an implementation of JBehave in Ruby.

A number of my co-workers have been using BDD techniques on a variety of real-world projects and have found the techniques very successful. The JBehave story runner – the part that verifies acceptance criteria – is under active development.

The vision is to have a round-trip editor so that BAs and testers can capture stories in a regular text editor that can generate stubs for the behaviour classes, all in the language of the business domain. BDD evolved with the help of many people, and I am hugely grateful to all of them.

DaveAstels has written an article about BDD in Ruby.

LizKeogh has updated the page on Wikipedia.

Implementations : Tools for implementing BDD.


ビヘイビア駆動開発

Behaviour-Driven Development


ソフトウェアのテスト品質を効果的に測定するミューテーション解析

RevAjaxMutator


テスト駆動開発

テスト駆動開発 (てすとくどうかいはつ、test-driven development; TDD) とは、プログラム開発手法の一種で、プログラムに必要な各機能について、最初にテストを書き(これをテストファーストと言う)、そのテストが動作する必要最低限な実装をとりあえず行った後、コードを洗練させる、という短い工程を繰り返すスタイルである。多くのアジャイルソフトウェア開発手法、例えばエクストリーム・プログラミングにおいて強く推奨されている。近年はビヘイビア駆動開発へと発展を遂げている。

テスト駆動開発で用いられるテストは、品質のためのテストではない。

したがって、コード本体とは独立してあらゆるケースを網羅するテスト、すなわち「テストそのものが価値を持つようなテスト」を目指しているわけではない。
テスト駆動開発におけるテストとは、コード本体とテストを合わせて検討することで、開発者がその正しさに確信を得るようなものである。
したがって、開発者の確信に少しも寄与しないテスト(また、ドキュメントとしてテストの読者に何かを伝えるために書かれていないもの)は、むしろ積極的に削除を検討する。

紹介 Azusa Nakano

中野システム研究所 所長

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください