6

データベース内の複数の行で新しいストアド プロシージャをテストする必要があるテスト アプリケーションを作成するように依頼されました。本質的には、次のようなことをしたいと考えています。

[Test]
public void TestSelect()
{
    foreach(id in ids)
    {
        DataTable old = Database.call("old_stored_proc",id);
        DataTable new_ = Database.call("new_stored_proc",id);

        Assert.AreEqual(old.Rows[0]["column"],ne_.Rows[0]["column"]);
    }
}

このテストを実行すると、1 つの行が他の行と一致しない場合、テスト全体が失敗します。代わりに、アサーションが渡された回数と失敗した回数を数えたいと思います。NUnitでこれを行う方法はありますか?

NUnit はやり過ぎかもしれませんが、これがなければ簡単な作業であることに気付きました...ただそれを学びたかっただけです。;)

4

8 に答える 8

9

あなたは間違ったことを主張しているようです。すべての値をチェックして、エラーがないことを確認したい (またはエラーの数を表示したい) 場合は、次のようにします。

[Test]
public void TestSelect()
{
    int errors = 0;
    foreach(id in ids)
    {
        DataTable old = Database.call("old_stored_proc",id);
        DataTable new_ = Database.call("new_stored_proc",id);

        if (old.Rows[0]["column"] != new_.Rows[0]["column"])
        {
            errors++;
        }            
    }

    Assert.AreEqual(0, errors, "There were " + errors + " errors.");
}
于 2008-10-03T16:07:19.403 に答える
5

1) ID が一定で、テストの実行時に検索されない場合は、ID ごとに個別の単体テスト フィクスチャを作成します。そうすれば、どの ID が実際に失敗しているかがわかります。データ駆動型テストの問題については、こちらを参照してください:
http://googletesting.blogspot.com/2008/09/tott-data-driven-traps.html

2) ID を動的に検索する必要があり、各 ID のフィクスチャを作成できない場合は、1 つの変更を加えた akmad の提案を使用してください。値が等しくない ID のリストを保持し、そのリストをエラー メッセージに追加します。どの ID がエラーの原因なのかわからないため、エラーの数だけを示す失敗したテストを診断することは非常に困難です。

3) NUnit で行うのがどれほど難しいかはわかりませんが、PyUnit では、動的に生成されたデータでテストを実行する必要がある場合、動的にテスト フィクスチャを作成し、それらを TestCase クラスにアタッチして、失敗するようにします。合格しないデータの各部分をテストします。Python の動的機能がなければ、これははるかに難しいと思いますが。

于 2008-10-03T16:21:56.130 に答える
4

質問は特に NUnit に関するものであることは知っていますが、興味深いことに、Gallio/MbUnitには、一度に複数のアサーションを実行してキャッチできる機能があります。

[Test]
public void MultipleTest()
{
    Assert.Multiple(() =>
    {
       Assert.IsTrue(blabla);
       Assert.AreEqual(pik, pok);
       // etc.
    }
}

は失敗したアサーションをすべてAssert.Multipleキャッチし、テストの最後にそれらを報告します。

于 2010-05-28T06:22:03.517 に答える
1

一致しない行の数を数えてから、この数を 0 と比較し、メッセージ内の一致しない文字列の数を返すアサーションを記述します。

これにも使用できますAssert.Greater

PS原則として、ユニットテストごとに1つのアサーションを実行するようにしてください。それが要点です。

于 2008-10-03T16:03:54.107 に答える
0

設定した目的に基づいて、ある行が別の行と一致しない場合、テスト全体が失敗するはずです。アサーションが成功または失敗した回数を数えても、期待した結果と実際に得た結果を比較するよりも情報が少なくなります。

于 2008-10-09T13:43:53.357 に答える
0

カウンターを宣言し、カウンターの値をアサートして合格/不合格を判断できます。

また、テスト セットアップで作業の大部分を実行してから、複数のテストを作成することもできます。

同じテストですべての assert stmts が必要な理由がよくわかりません。

于 2008-10-03T16:01:12.910 に答える
0

私は最近同じ問題を抱えていました。エラーをカウントするというアイデアを Yann Trevin の Assert.Multiple の言及と組み合わせて、次のようなことができる IEnumberable の拡張メソッドを作成しました。

[Test]
public void TestEvenNumbers()
{
    int[] numbers = new int[] { 2, 4, 12, 22, 13, 42 };
    numbers.AssertAll((num) => Assert.That((num % 2) == 0, "{0} is an odd number", num));
}

NUnit の出力は次のようになります。

TestEvenNumbers:
  5 of 6 tests passed; 0 inconclusive
FAILED: 13:   13 is an odd number
  Expected: True
  But was:  False

  Expected: 6
  But was:  5

OPの問題の解決策は次のとおりです。

[Test]
public void TestSelect()
{
    ids.AssertAll(CheckStoredProcedures);
}

private void CheckStoredProcedures(Id id)
{
    DataTable old = Database.call("old_stored_proc",id);
    DataTable new_ = Database.call("new_stored_proc",id);

    Assert.AreEqual(old.Rows[0]["column"], new_.Rows[0]["column"]);
}

拡張メソッドは次のとおりです (Linq 用語との一貫性を保つために、「複数」ではなく「すべて」を使用したことに注意してください)。

using System;
using System.Text;
using System.Collections.Generic;
using NUnit.Framework;

public static class NUnitExtensions
{
    public static void AssertAll<T>(this IEnumerable<T> objects, Action<T> test)
    {
        int total = 0;
        int passed = 0;
        int failed = 0;
        int inconclusive = 0;
        var sb = new StringBuilder();
        foreach (var obj in objects)
        {
            total++;
            try
            {
                test(obj);
                passed++;
            }
            catch (InconclusiveException assertion)
            {
                inconclusive++;
                string message = string.Format("INCONCLUSIVE: {0}: {1}", obj.ToString(), assertion.Message);
                Console.WriteLine(message);
                sb.AppendLine(message);
            }
            catch (AssertionException assertion)
            {
                failed++;
                string message = string.Format("FAILED: {0}: {1}", obj.ToString(), assertion.Message);
                Console.WriteLine(message);
                sb.AppendLine(message);
            }
        }

        if (passed != total)
        {
            string details = sb.ToString();
            string message = string.Format("{0} of {1} tests passed; {2} inconclusive\n{3}", passed, total, inconclusive, details);
            if (failed == 0)
            {
                Assert.Inconclusive(message);
            }
            else
            {
                Assert.AreEqual(total, passed, message);
            }
        }
    }
}
于 2014-05-09T17:48:39.607 に答える