web-dev-qa-db-ja.com

BDDを使用する場合の単体テストの使用方法

BDDを理解しようとしています。私はいくつかの記事を読みましたが、理解したとおり、BDDはTDDの「次のステップ」です。私は両方とも非常に似ていることがわかり、そして この記事 で読み取れるように、BDDはTDDからの改善として生まれました。すばらしい、私はこのアイデアが本当に好きです。

私が理解できない実用的なポイントが1つあると考えました。BAがシステムが持つすべての予想される動作を書き込む.featureファイルがあります。 BAとして、彼はシステムがどのように構築されるのか理解していないので、次のように記述します。

+シナリオ1:アカウントは信用状態です+

アカウントが信用されていると仮定

そしてカードは有効です

ディスペンサーには現金が入っています

顧客が現金を要求したとき

次に、口座からの引き落としを確認し、現金が分配されるようにします

そして、カードが返されることを確認してください

OK、これはすばらしいですが、システムの多くの部分が協調して実行できるようになっています(Account obj、Dispenser obj、Customer objなどを考えてみてください)。私にはこれは統合テストのように見えます。

単体テストをお願いします。ディスペンサーにお金があるかどうかを確認するコードをテストするにはどうすればよいですか?それとも現金が分配されるのですか?または、必要に応じて口座から引き落とされますか? 「BA Created」テストとユニットテストを混在させるにはどうすればよいですか?

18
JSBach

振る舞い駆動型開発とテスト駆動型開発は補完的なものですが、相互に置き換わるものではありません。

アプリケーションの「動作」は、受け入れテストで説明されています。受け入れテストは、BDDによると、Cucumberで記述された機能とシナリオになります。

各小さなコンポーネントがどのように機能するかについての要点は、単体テストで説明されています。単体テストの結果は、Cucumberで作成したシナリオをサポートします。

車を作るプロセスを想像してみてください。

最初に、製品チームは彼らのアイデアを思い付き、最終的にそれらを使用シナリオに要約します。

Scenario: Starting the car
    Given I am standing in front of the drivers door
    When I open the door
    Then the door should lift up DeLorean-style (yeah, baby!)
    When I get into the car
    And turn the key
    Then the engine roars to life

このシナリオは少しばかげているように聞こえるかもしれませんが、非常に高いレベルの製品とエンドユーザーに焦点を当てた要件です。ドアを開け、キーを回してエンジンを始動するだけでは、さまざまなコンポーネントが多数連携して動作します。この1つのテストでは、車両が正常に機能することを確認するには不十分です。スターター、バッテリー、オルタネーター、キー、イグニッションスイッチをテストする必要があります。これらの各コンポーネントには独自のテストが必要です。

上記のシナリオは「全体像」テストです。車両の各コンポーネントには、全体が適切に機能することを確認するための「小画像」テストが必要です。

ソフトウェアの構築とテストは、多くの点で同じです。トップダウンで設計し、ボトムアップで構築します。エンジンをかけられないのに、ドアが上がるのはなぜですか?バッテリーがないのになぜスターターがあるのですか?

製品チームが受け入れテストを考案し、キュウリで肉付けします。これにより、「全体像」がわかります。適切なコンポーネントとそれらがどのように相互作用するかを設計し、各コンポーネントを個別にテストするのは、エンジニアリングチーム次第です。これらがユニットテストです。

単体テストに合格したら、キュウリシナリオの実装を開始します。それらが合格したら、製品チームが要求したものを提供します。

28
Greg Burghardt

BDDを理解しようとしています。私はいくつかの記事を読みましたが、理解したとおり、BDDはTDDの「次のステップ」です。私は両方とも非常に似ていると思うので、この記事で読むことができるように、BDDはTDDからの改善として生まれました。

実際、いいえ、BDDはTDDからの「次のステップ」ではありません。それはisTDDです。より正確には、これはTDDの言い換えです。

BDDの作成者は、TDDがテストではなく動作仕様であることを理解するための主なハードルは、すべてのTDD用語がテストに関するものであり、動作仕様に関するものではないことに気付きました。それは、誰かが「ピンクの象を考えないようにしよう」と言ったときにピンクの象を考えないようにすることのようなものですが、ピンクの象でいっぱいの部屋にいると、「ピンクの象、ピンクあなたの耳に象、ピンクの象」。

したがって、彼らは行動仕様の観点からTDDを言い換えました。 「テスト」と「テストケース」は「例」、「ユニット」は「動作」、「アサーション」は「期待」などになりました。

ただし、方法論は同じです。まず、受け入れテスト(つまり「機能」)、ズームインユニットテスト(つまり「例」)、縮小ズームなどを行います。 。

単体テストをお願いします。ディスペンサーにお金があるかどうかを確認するコードをテストするにはどうすればよいですか?それとも現金が分配されるのですか?または、必要に応じて口座から引き落とされますか? 「BA作成済み」テストと単体テストをどのように混合できますか?

TDDで行うのと同じ方法です。機能と例をさまざまなフレームワーク(CucumberやRSpecなど)またはさまざまな言語(たとえばCのCプロジェクトの例を記述し、FIT/Fitnesseの機能を記述するなど)で記述できます。両方で単一の機能フレームワークを使用できます(例:Cucumberで例と機能を書く)または両方に単一の例のフレームワークを使用できます(例:RSpecで両方を書く)。フレームワークを使用する必要すらありません。

単一のフレームワークのみを使用したTDD-done-right(BDDと同じ)の例は、JUnit自体です。これには、ユニットテスト(例)と機能/統合テスト(機能)が混在し、すべてJUnit自体で記述されています。

ケントベックはこれを「ズーム」と呼んでいると思います。高レベルで開始し、詳細に「ズームイン」してから、もう一度元に戻します。

9
Jörg W Mittag

免責事項:私はBDDの専門家ではありませんが、リンク先の記事について私の見解を述べたいと思います。

TDDは実装手法です。最初にテストを記述してから、メソッドを実装し、テストを実行してリファクタリングし、同じメソッドまたは新しいメソッドにさらにテストを追加します。 TDDは、クラス名またはメソッド名の選択方法に関する規則を実際に定義していません。それはあなた次第です。 TDDはまた、「完了したら」とは通知しません。

したがって、新しいメソッドのテストを作成するときは常に、メソッド名を選択する必要があります。これが、BDDが登場するポイントです。上記のシナリオのビジネス用語を使用してメソッド名を選択し、説明の方法でメソッド名を選択します。あなたのクラスの振る舞い、あなたはBDDをしています。 「さらにテストを追加する必要があるか」と自問するときはいつでも、BAによって提供されるシナリオを確認し、必要なすべてのパーツを完全に実装しているかどうかを確認できます。そうでない場合は、さらにテストを追加する必要があります。

記事の作成者は、テストの名前を選択するときに、より行動に関連した命名スキームを使用することも提案しています。そのため、JUnitを、各テストケースで始まる命名スキームに依存しないツールに置き換えることを提案しています。 「テスト」という名前。私はJBehaveを知りませんが、それがそのツールとJunitの主な違いだと思います。

さらに、BDDシナリオは統合テストの青写真にもなります。通常、追加するのはafterメソッド名をTDDで具体化し、妥当な量の単体テストを追加した後です。

したがって、私の理解では、TDDはBDDの一部として使用できる手段であり、BDDは適切なテストを記述し、それらに適切な名前を付けるのに役立ちます。

1
Doc Brown