web-dev-qa-db-ja.com

テスト駆動開発-実装コードが存在しない前にテストを作成する方法

私はTDDを学んでいますが、それは簡単ではないため、採用に苦労しています。

私が答えられない質問は、「実装コードが存在する前にテストを書く方法?」です。

ターゲットクラス/ターゲットメソッド/ターゲットパラメータタイプ/ターゲットリターンタイプが存在しない場合、

  • テストでコードを書いているときに何を参照しますか。テストの作成を開始するにはどうすればよいですか?
  • 実際の実装コードの前にテストメソッド名だけを記述できた場合、テストはどのように失敗しましたか?

誰もがなぜではなくHOWではない

実稼働コードの前にテストを記述することを念頭に置いたリソースを見つけるために最善を尽くしましたが、良いリソースを逃したと仮定すると、それらのほとんどは、それを採用するプラクティスに焦点を合わせるよりもTTDが重要である理由を説明する決まり文句でいっぱいです。

ユースケースの例

大学向けのソフトウェアを開発しており、ユースケースがコース登録であると仮定しましょう。

簡潔にするために、この議論を

  • シナリオ:「学生は学期ごとに最大3つのコースに登録できます」
  • サービス層とdao層のテスト。

擬似コード

ENROLL(studentId, courseId)
    //check if student enrolled in less than 3 courses in the same semester as given courseId belongs in.
    //if yes, enroll him/her.
    //if not, return an error.

上記の実際の実装は、サービス、daosなどを含むいくつかのクラスに及ぶ可能性があります。

ステップごとにテスト駆動開発する方法を説明してください。 TDDを使用してこれを実装する場合、ステップバイステップでどのように実行しますか。

これが将来私のような多くの闘争を助けることを願っています。

48
phani

EnrollingServiceと同じパッケージでsrc/test/JavaにEnrollingServiceTestクラスを作成します

class EnrollingServiceTest {
    private EnrollingService enrollingService;

    @Before 
    public void init() {
           enrollingService = new EnrollingService();
    }

    @Test
    public void testEnroll() {
           boolean result = enrollingService.enroll(1l, 1l);
           assertTrue(result);
    ...

IDE(IDEを使用していると仮定しています)にエラーが表示されます-EnrollingServiceは存在しません。

EnrollServiceにカーソルを合わせる-IDEはクラスの作成を提案します-src/main/Javaで作成します

今IDEは、enroll(long、long)メソッドが欠落していると言います-let IDE作成してください。

IDEはエラーを表示しません。テストを実行します-失敗します。登録してロジックの実装を開始します。

等々...

43

これは、コードの実装ではなく、コードの予想される動作に焦点を合わせると、より明確になります。したがって、概説したシナリオを考えると、何らかのクラスでenroll()メソッドを作成する必要があるという結論に達する可能性があります。その後、このクラスをテストする方法を検討できます。

まず、クラスの条件とそれに期待されることを検討します。クラスの特定の不変式を識別できる場合があります。その場合、クラスをテストするには、その不変式に違反する可能性のある方法を検討します。

そのため、ステートメントを取る:学生は学期ごとに最大3つのコースに登録することができます、あなたはこれが起こりうる方法を考慮します。

  1. 学生は指定された学期の0コースに登録され、コースへの登録を試行します。結果:登録が成功しました。学生は指定された学期の1コースに登録されました。
  2. 学生は指定された学期の1コースに登録され、コースに登録しようとします。結果:登録成功学生は現在、指定された学期の2つのコースに登録されています。
  3. 学生は指定された学期の3つのコースに登録され、コースへの登録を試みます。結果:失敗(例外がスローされる可能性がありますか?)
  4. などなど

次に、これらのテストを実際に作成します。これらはそれぞれテスト方法になります。したがって、テストメソッドは、オブジェクトが作成され、環境が期待どおりに設定されていることを確認します。次に、メソッドを呼び出して、結果を期待される結果と比較します。あなたが実際に起こることを期待することが実際に起こるなら、テストは合格です。

さて、最初は、まだメソッドを書いていないので、テストは実際には合格しません。しかし、コードの記述を開始すると、テストは合格し始め、最終的にテストの100%が合格し、その時点でコードが要件を満たしていることに満足します。

4
public void shouldNotEnrollInMoreThanFourClassesInASemester() {
  Enroller enroller = new Enroller();
  Student student = new Student();
  Semester one = new Semester();
  Semester two = new Semester();
  Course geology = new Course(one);
  Course architecture = new Course(one);
  Course calculus = new Course(one);
  Course sociology = new Course(one);
  Course geometry = new Course(two);

  assertOk(enroller.enroll(student, geology));
  assertOk(enroller.enroll(student, architecture));
  assertOk(enroller.enroll(student, calculus));
  assertNotOk(enroller.enroll(student, sociology));
  assertOk(enroller.enroll(student, geometry));
}
3
Carl Manaster

シナリオでは、各レイヤーを個別にテストする必要があるため、サービスレイヤーをテストするときにdaoをモックアウトします。

最初にテストを作成するとき、コンパイルされません。つまり、テストは失敗しますが、クラスが存在しないので問題ありません。

あなたの例では、最大3つのコースに登録するためにどのレイヤーを実施する必要がありますか?それはテスト方法に影響します。

最初にテストを書くことは、これらのタイプの質問に取り組むのに役立ちます。

前述のように、これは決定的な答えにはあまりにもオープンエンドですが、テストの作成を開始した場合、更新として投稿すると役立つ場合があります。

したがって、daoテストを作成してからクラスとメソッドを作成してコンパイルしますが、実装が完了するまで失敗します。 2,3,4クラスの登録をテストし、それぞれが適切に失敗することを確認してから、実装を終了することをお勧めします。

1
James Black