web-dev-qa-db-ja.com

単体テスト:Linqによる遅延アサーション

このような遅延アサーションを追加しても問題ありませんか

var actualKittens = actualKittens.Select(kitten => {
    Assert.IsСute(kitten);
    return kitten
});

どうして?したがって、たとえば、マテリアライズドコレクションを期待するステートメントでも、1回だけ繰り返すことができます。

CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

また、Selectだけでなく、イテレータが定義され、多数のチェックとロジック(たとえば、いくつかのカウントやフィルタリング)を持つメソッドでもかまいません。

疑いの種は、テストが失敗した場合にそのようなコードを読み取り、デバッグする複雑さです。

18
SerG

このような遅延アサーションを追加しても大丈夫ですか[..]

いいえ、そうではありません。どうして? 何らかの理由で2番目のアサートを削除した場合、テストは緑色に変わり、テストは引き続き機能すると考えられますが、コレクションが列挙されないため、動作しません。2つ以上の独立したアサーションがある場合、そのうちの1つを無効にしても、その仕事を続けます。

この組み合わせを考えてみましょう:

Assert.IsTrue(actualKittens.All(x => x.IsCute());
CollectionAssert.AreEquivalent(expectedKittens, actualKittens.ToList());

これで、アサートの1つを無効化または削除した場合でも、他のアサートは引き続き機能します。また、コレクションを具体化するためにforgetした場合、実行に時間がかかる可能性がありますが、引き続き機能します。独立したテストはより堅牢で信頼性があります。

2番目のnoもあります。他のフレームワークがそれをどのように処理するかはわかりませんが、MSテストプラットフォームを使用している場合、どのテストが失敗したかはわかりません。失敗したテストをダブルクリックすると、CollectionAssertが失敗したと表示されますが、実際には、ネストされたAssertが原因で問題が発生し、デバッグが非常に困難になります。次に例を示します。

    [TestMethod]
    public void TestMethod()
    {
        var numbers = new[] { 1, 2, 3 }.Select(x =>
        {
            Assert.Fail("Wrong number.");
            return x;
        });

        // This will fail and you won't be sure why.
        CollectionAssert.AreEqual(new[] { 1, 2, 3 }, numbers.ToList()); 

    }

つまり、最初のテストはバグの発見に役立たないため、実際には役に立たないということです。番号が無効だったために失敗したのか、両方のコレクションが異なっていたために失敗したのかはわかりません。


どうして?したがって、マテリアライズドコレクションを期待するステートメントでも、1回だけ繰り返すことができます。

なぜあなたはそれを気にかけているのでしょうか?これらは単体テストです。それらのすべてを最適化する必要はありません。通常、テストでは何百万ものアイテムが必要ないため、パフォーマンスは問題になりません。

あなたはそのようなテストを維持する必要があるでしょう、それでなぜあなたはそれらをより複雑にする必要があるのですか?機能する単純なアサートを記述します。

37
t3chb0t