2

私は、単体テストには多くではなく 1 つのアサーションを含める必要があるという Osherove の意見に同意します。しかし、そのプリンシパルを ASP.NET MVC 単体テストに適用すると、厳しすぎるのではないかと思います。次のテストを検討してください。

    [TestMethod] 
    public void RedirectTest() {     
        // Arrange - create the controller   
        ExampleController target = new ExampleController();     

        // Act - call the action method     
        RedirectResult result = target.Redirect();   

        // Assert - check the result
        Assert.IsFalse(result.Permanent);     
        Assert.AreEqual("/Example/Index", result.Url); 
    }

    [TestMethod]
    public void RedirectValueTest() {     
        // Arrange - create the controller     
        ExampleController target = new ExampleController();     
        // Act - call the action method     
        RedirectToRouteResult result = target.Redirect();     
        // Assert - check the result     
        Assert.IsFalse(result.Permanent);     
        Assert.AreEqual("Example", result.RouteValues["controller"]);    
        Assert.AreEqual("Index", result.RouteValues["action"]);    
        Assert.AreEqual("MyID", result.RouteValues["ID"]); 
    }

確かに、上記の 2 つのテストは 6 つのテスト (それぞれ 1 つのアサート) に分割できますが、少し過剰に感じられます。これに関するベストプラクティスはありますか? 職業はなんですか?テスト専門家のコンセンサスがそこにある場合、私は確かにアサートごとに1つのテストの道をたどります...

4

5 に答える 5

2

アサーション
単体テストでは、焦点を絞った 1 つのシナリオのみをテストする必要があります。これは、複数の実際の物理アサートである場合もあれば、そうでない場合もあります。単一の物理アサートのみであることが望ましいですが、常に可能であるとは限りません。その要点は、各テストは特定の焦点を絞ったシナリオのみをカバーするということです。

名前付けと編成
ユニット テストの名前付けは非常に重要です。名前は、テストしているシナリオを反映している必要があります。

たとえば、単一の物理クラスをテストする複数のテスト クラスを持つことができます。これは、テストを関連するグループに分割し、1 つのテスト クラスを非常に多くのコード行で埋めて判読不能にならないようにするための良い方法でもあります。

私が以前に行ったことは、開発者がテスト対象のクラスの名前でテスト フォルダーを作成することです。そのフォルダには、テストの各論理グループのテスト クラスが含まれています。各クラスには、文のように聞こえるメソッドがあります。

テストするクラスが呼び出されMyCalculatorたので、という名前のフォルダーを作成するとしますMyCalculator.Tests。そのフォルダで、論理テストのセットごとにテスト クラスを作成できるようになりました。MultiplicationTestsorDivisionTestsなどの名前のクラスなどAdditionTests。各クラスには、その論理グループに関連するテスト メソッドを含めることができます。

たとえば、追加テストの場合、次のようなテスト メソッドを使用できます。

  • When_adding_any_2_numbers_then_result_is_correct
  • When_adding_small_negative_and_large_positive_numbers_then_result_is_correct_positive
  • When_adding_large_negative_and_small_positive_numbers_then_result_is_correct_negative

各テストは特定のシナリオのみをテストし、テストの名前もそれを非常によく表しています。

シナリオを非常に多くのテストに分割するのはなぜですか? そうすることで、ほとんどの場合、各テスト内で 1 つの焦点を絞ったシナリオのみをテストするようになります。また、将来バグが発生したときに、直接影響を受けるテストのみが壊れていることを確認します。

たとえば、ある段階でバグがあり、加算の結果が負の数の場合に add メソッドが例外をスローする場合、テストまたは負の結果のテストに関係するテストのみが影響を受けます。

さらに、多くのシナリオをアサートするテストがあり、何がテストに失敗しているのか実際にはわからない場合、焦点を絞った単体テストの作成に費やす時間は、後の段階で必要なコストと時間をはるかに上回ります。

テストを編成する方法は多数ありますが、一般的な目的は常に同じで、各テストで特定の焦点を絞ったシナリオのみをテストする必要があります。

あなたのシナリオ
あなたのシナリオでは、たとえばRedirectTest、テスト内で失敗すると失敗Assert.IsFalse(result.Permanent);します。これは必ずしもリダイレクトが失敗したことを意味するわけではありません。テストは、期待される URL にリダイレクトされず、他に何もリダイレクトされない場合にのみ失敗します。ページのコンテンツが期待どおりにレンダリングされない場合、またはデータが欠落している場合は、その特定のテストには関係ありません。

于 2012-04-20T20:10:29.890 に答える
2

私が目にする最初の問題は、テスト名です...単体テストが実際にテストすることになっているものを言っていません。私はそれらのテストのいくつかを分割します。この最初のテストではAssert.IsFalse(result.Permanent)、両方のテストから が削除されます。

[TestMethod] 
public void Redirect_result_should_set_Permanent_to_false() {     
    // Arrange - create the controller   
    ExampleController target = new ExampleController();     

    // Act - call the action method     
    RedirectResult result = target.Redirect();   

    // Assert - check the result
    Assert.IsFalse(result.Permanent);     
}

なぜこれを行う必要があるのですか?の場合result.Permanent == true、両方のテストが失敗しますが、その理由はわかりません。この場合、その理由がわかります。

于 2012-04-20T18:32:12.337 に答える
0

テストは、個別のコード パスをテストしている限り、必要な数のアサーションを持つことができます。テストごとにアサーションを 1 つしか持たないのは、テストを維持するという点でやり過ぎのように思えます。

于 2012-04-20T17:56:08.790 に答える
0

個人的には、テストごとに 1 つのアサートを保持する傾向があります。Asp .Net MVC コントローラーをテストしているときに、1 回のテストで最大 4 つ (個人的な経験則) のアサートを保持することがあります。

テストごとに複数のアサートを持つことの問題は、たとえば、最初のアサートが失敗したときに、残りのアサートで何かが間違っているか正しいかがわからないため、コードを修正して最初にassert は、2 番目のアサートが別の理由で失敗したことを確認するためだけに合格しました。

コントローラーで非常に具体的なものをテストしている場合でも、結果に正しいビュー名が含まれていて、関連付けられたモデルに期待されるデータが含まれている場合など、複数のアサートが理にかなっていることがあります。この場合、そのアプローチの短所を十分に理解して 1 つのテストに複数のアサートを配置するか、メソッド内のテストの手配セクションと行為セクションを抽出して、そのメソッドを呼び出すいくつかのテストを作成し、結果を取得して結果を得ることができます。特定のデータに対してアサートします。

于 2012-04-23T19:29:35.680 に答える
-1

アサートを 1 つだけ持つべきだと言う人がいる主な (?) 理由は、一度に 1 つのアサートからしか失敗のフィードバックを取得できないためです。つまり、アサートを別のテストに配置すると、より多くのフィードバックが得られます。

ただし、テストごとに複数のアサーションを使用できると思います。読みやすさなど、より重要な側面が他にもあります。より多くのテストを行うと、より多くのコードを読み取ることができ、テスト スイートの概要を把握することがより困難になります。

ただし、重要なアサーションはすべてテスト内に配置する必要があると思います。そうすれば、それを見つけるために他の場所に行く必要がなくなり、把握が難しくなります。重要とは、テストが検証することを目的としていることを意味します。たとえば、テストが意味をなすために機能しなければならないもの、他のテストがより明確に検証するものについて、アサーションを隠すことができます。

于 2012-04-20T18:48:11.303 に答える