是否可以改进以下单元测试,以遵循任何.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));
}
}
答案 0 :(得分:2)
首先,您可以改进单元测试的名称 NarrowDown_Works
非常模糊,我无法分辨测试中的课程应该做什么。
你有很多断言和大量数据,我不知道什么是重要的。尝试将测试分解为更小的测试,并且更容易为它们命名。如果可能的话,每次测试使用一个断言。
您构建测试数据非常复杂,请考虑使用匹配器(如NHamcrest)来减少所需的断言数据量,而不是使用Is.EquivalentTo
。
您还可以使用构建器或工厂构造函数来使Constraint
类的使初始化更简单更简单,而不是传入Ranges
的数组。
答案 1 :(得分: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));
}
}
看看您的测试方法现在变得多么简单了?此外,这将使来自原始测试用例源的每组数据在单独的测试中运行,因此整个事情不会因为一组数据导致失败而失败。请记住:测试应仅断言一个事物。
HTH!