[翻訳]Behavior-driven Development(BDD)行動駆動開発(一)

10135 ワード

簡単に言えば、BDDは一連のTDDに基づくツールと方法セットから発展した開発モデルであり、一般的には新しい開発モデルとは考えられず、TDDの補完として用いられる.そこで,まずTDDの概念について行う.

テスト駆動開発(TDD)


TDDモードは反復的な開発プロセスを採用している.ソフトウェアの各機能特性の開発は,的確なテストの作成から始まる.最初はテストに失敗し、開発者は次の手順で反復します.
1.テストを作成し、合格していないかどうかを観察する.
2.テストに合格するために、以前のバージョンを実装します.
3.必要に応じて、コードの一部を再構築します.他のテストの作成を続行します.  

単純な例(Rubyベース)


ユーザ管理機能を開発するとします.ユーザは、後で名前を使用して取得できるように名前で初期化する必要があります.
最初のテスト:
describe User do
  it "lets me assign a name" do
    user = User.new "Paul"
    user.name.should == "Paul"
  end
end

<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
運転後にエラーが発生します
uninitialized constant User


<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
 
テストを作成するときは、テストが最初に実行されたときに必ず失敗していることを常に確認してください.これは、成功した機能をテストしていないことを意味します.次に、userの内容を記述します.
class User

end

テストを続行し、エラーを報告します.
ArgumentError: wrong number of arguments (1 for 0)

<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
次に、パラメータとして名前を受け入れるコンストラクタを実装します.
class User

  def initialize name

  end

end

テストを続行すると、エラーが発生します.
NoMethodError: undefined method 'name'

<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
次に関数nameを追加すると、テスト結果は次のとおりです.
user.name.should == "Paul" expected: "Paul" got: nil

<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
次にnameに値を割り当て、最後に次のようにします.
class User

  def initialize name

  end

  

  def name

    "Paul"

  end

end

<!--
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
-->
このユーザーは常にPaulと呼ばれていますが、まだ実装されていない詳細があります.これまで作成したテストは確かに順調に合格しました.TDDの原則に従って,コードを再構築できるようになった.具体的なコードは説明されませんが、まずテストを追加する必要があります.
describe User do

  it "lets me assign a name" do

    user = User.new "Paul"

    user.name.should == "Paul"

  end

  

  it "lets me assign a different name" do

    user = User.new "Sarah"

    user.name.should == "Sarah"

  end

end

テストを続行するか、エラーが発生します.
user.name.should == "Sarah" expected: "Sarah" got: "Paul"


これは予想外のエラーなので、テストに合格するまで修正を続けます.
class User

  def initialize name

    @name = name

  end

  

  def name

    @name

  end

end

ここで私たちは所望の機能を完成しました.しかし、コードの再構築は停止せず、Rubyは後で簡単な属性を読み取る方法attr_を提供した.reader.したがって、再構築されたコードは次のようになります.
class User

  attr_reader :name

 

  def initialize name

    @name = name

  end

end

TDDの理由


テストドライバ開発の手順は冗長に見えますが、私たちがそうする必要がある理由は何ですか?
多くのアプリケーションは、開発の初期段階では細かく見えますが、概要は簡単ですが、数週間後にはゴミの山になり、予想できない「サプライズ」に満ちています.唯一の解決策は、コードの作成後に手動でテストするたびに、テストに数週間かかるかもしれません.
TDDは開発者をより敏捷にし,慎重で緩やかなスタートを切り,後期に埋蔵された地雷を踏むことを避けることができる.重要なのは、数年後にアプリケーションが膨大で煩雑になり、すべての情報資料が失われても、テストはプログラムが正常に動作することを保証することができます.

TDDと持続的統合


テストの唯一の問題は、時間が経つにつれて、かかる時間が倍増することです.すべてのテストを実行するには、時間がかかる可能性があります.良い解決策はCIの導入である(Continuous Integration).これに基づいて、自動コンパイル、導入などのスキームを導入し、手動介入を低減し、テストの実行と後続のプロセスを自動化することもできます.

結論


TDDの利点は、追加の努力によって長期的なリターンを獲得し、アプリケーションの迅速さ、速度、セキュリティを得ることです.
 
ソース:http://blog.codeship.io/2013/04/16/tests-make-software.html