1

.NET TDD / BDDフレームワークのいずれかで優れたTDD設計手法(名前付け、行テストの使用、クラスの設計)に従うために、次の単体テストを改善できますか?

また、この(NUnit)の例のように、各行に対して個別の期待値を持つことができる行テストを行うためのより良い方法は、フレームワークのいずれかにありますか?

ここでテスト対象のシステムConstraintは、有効な整数の複数の範囲を持つことができるクラスです。テストテストは、NarrowDown別の制約に基づいて有効範囲を小さくできる方法をテストします。

[TestFixture]
internal class ConstraintTests
{
    [Test]
    public void NarrowDown_Works()
    {
        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) });

        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50), new Range(60, 70) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) });

        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49), new Range(60, 70) });
    }

    private static void RowTest_NarrowDown(IEnumerable<Range> sut, IEnumerable<Range> context)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Null);
    }

    private static void RowTest_NarrowDown(IEnumerable<Range> sut, IEnumerable<Range> context, IEnumerable<Range> expected)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Not.Null);
        Assert.That(result.Bounds, Is.EquivalentTo(expected));
    }
}
4

2 に答える 2

2

まず、ユニットテストの名前を改善することができます。これNarrowDown_Worksは非常にあいまいであり、テスト対象のクラスが何をしているのかわかりません。

たくさんのアサーションとたくさんのデータがありますが、何が重要かわかりません。テストをより小さなテストに分割してみてください。そうすれば、それらにも名前を付けるのが簡単になります。可能であれば、テストごとに1つのアサーションを使用します。

テストデータの構築は非常に複雑です。NHamcrestなどのマッチャーを使用して、を使用する代わりに必要なアサーションデータの量を減らすことを検討してください。Is.EquivalentTo

ビルダーまたはファクトリコンストラクターを使用して、の配列を渡すのではなく、クラスの初期化を簡単にすることもできます。ConstraintRanges

于 2011-10-27T20:53:55.740 に答える
0

データファクトリではデータ駆動型のアプローチを使用する必要があります(NUnitと言えば、テストケースソースと呼ばれます)。これにより、テストの読み取り、理解、変更、および保守がはるかに簡単になります(または、より一般的には、はるかにクリーンになります)。

[TestFixture]
internal class ConstraintTests
{
    static object[] TwoRanges = 
    {
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49), new Range(60, 70) }
            }
    };

    static object[] ThreeRanges = 
    {
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) }
            },
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50), new Range(60, 70) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) }
            }
    };

    [Test, TestCaseSource("TwoRanges")]
    public void NarrowDown_WhenCalledWithTwoRanges_GivesTheExpectedResult(IEnumerable<Range> sut, IEnumerable<Range> context)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Null);
    }

    [Test, TestCaseSource("ThreeRanges")]
    public void NarrowDown_WhenCalledWithThreeRanges_GivesTheExpectedResult(IEnumerable<Range> sut, IEnumerable<Range> context, IEnumerable<Range> expected)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Not.Null);
        Assert.That(result.Bounds, Is.EquivalentTo(expected));
    }
}

テスト方法がどれほど簡単になったか見てみましょう。また、これにより、元のテストケースソースからのデータの各セットが個別のテストで実行されるため、1つのデータセットが失敗を引き起こしたという理由だけですべてが失敗することはありません。注意:テストでは、1つのことだけをアサートする必要があります。

HTH!

于 2011-10-30T17:54:02.000 に答える