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非常模糊,而且我无法说出被测类应该做什么。

你有很多断言和大量数据,我不知道什么是重要的。尝试将您的测试分解为更小的测试,这样也更容易命名它们。如果可能,每个测试使用一个断言

您的测试数据构造非常复杂,请考虑使用Nhamcrest之类的匹配来减少您需要的断言数据量,而不是使用Is.EquivalentTo.

您还可以使用构建器或工厂构造函数来简化类的初始化Constraint而不是传入Ranges.

于 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));
    }
}

看看您的测试方法现在变得多么简单?此外,这将使来自原始测试用例源的每组数据在单独的测试中运行,因此整个事情不会仅仅因为一组数据导致失败而失败。记住:一个测试应该只断言件事。

于 2011-10-30T17:54:02.000 回答