【发布时间】:2013-08-15 19:16:27
【问题描述】:
我正在尝试更密切地遵循“每个单元测试一个断言”的做法。这并不总是可能的,但我确实发现它对于查明错误很有用。
例如我可能有类似的东西:
var toTest;
[TestInitialize]
Init() {
toTest = // Create toTest
}
[TestMethod]
TestIsCreated() {
Assert.IsNotNull(toTest);
}
[TestMethod]
TestIsProperty1Setup() {
Assert.IsNotNull(toTest.Property1);
// Maybe some more tests on Property1
}
// More tests for other properties...
问题是如果 toTest 的创建失败,那么所有其他单元测试也会失败。所以我们可以像这样添加一些检查:
...
[TestMethod]
TestIsProperty1Setup() {
if (toTest == null) Assert.Inconclusive()
Assert.IsNotNull(toTest.Property1);
// Maybe some more tests on Property1
}
...
这将停止级联故障并指出确切的问题。如果 // Create toTest 行返回 null,那么我会得到一个单元测试失败,以及一堆更不确定的测试。当我修复一个失败的测试时,其他一切都通过了。
这有两个地方会下降。一是我现在在几乎所有单元测试的开始都有重复代码。
第二个问题是当我想设置和检查一个更复杂的对象时(在这个虚拟示例中 toTest 也有一个数组):
[TestMethod]
TestArrayIsNotNull() {
if (toTest == null) Assert.Inconclusive();
Assert.IsNotNull(toTest.Array);
}
[TestMethod]
TestArrayIsInitilizedWithOneElement() {
if (toTest == null) Assert.Inconclusive();
if (toTest.Array == null) Assert.Inconclusive();
Assert.AreEqual(1, toTest.Array.Count())
}
[TestMethod]
TestArrayIsInitilizedWithCorrectElement() {
if (toTest == null) Assert.Inconclusive();
if (toTest.Array == null) Assert.Inconclusive();
if (toTest.Array.Count() != 1) Assert.Inconclusive();
// Assert something about toTest.Array[0]
}
现在每个单独的测试都有更多重复的代码,更重要的是,断言必须在不同的测试之间保持同步,这意味着一个小的更改可能会影响许多单元测试。
理想情况下,我希望在每个测试的顶部都有一个属性,并且只有在“先决条件”测试通过时才运行测试。它可能看起来像这样:
[TestMethod]
[OnlyRunIfOtherTestPasses(TestIsCreated())]
TestArrayIsNotNull() {
Assert.IsNotNull(toTest.Array);
}
[TestMethod]
[OnlyRunIfOtherTestPasses(TestArrayIsNotNull())]
TestArrayIsInitilizedWithOneElement() {
Assert.AreEqual(1, toTest.Array.Count())
}
[TestMethod]
[OnlyRunIfOtherTestPasses(TestArrayIsInitilizedWithOneElement())]
TestArrayIsInitilizedWithCorrectElement() {
// Assert something about toTest.Array[0]
}
单元测试现在非常简单 - 没有重复,并且现在可以自动保持测试与其“先决条件”同步。
有这样的吗?或者我可以使用完全不同的功能来获得相同的效果?
我知道将属性中的测试方法引用到另一个测试方法几乎肯定存在问题 - 您可能必须使用硬编码到方法名称的字符串(如果方法名称会发生什么情况更改,或该方法不存在)。我确信循环引用也存在潜在问题。但是,尽管存在所有这些问题,但一定有人已经解决了这个问题。谁能给我指点一下?
【问题讨论】:
-
恕我直言,您的单元测试逻辑太多。它们应该简明扼要,不包含太多逻辑。他们也不应该依赖其他测试。我认为你需要重新考虑你的方法。
-
当你说“重新考虑你的方法”时,你的意思是重新考虑单元测试的编写方式(我不应该一直检查 toTest 是否为空),或者重新考虑下类的依赖关系test(toTest 不应该有一个必须设置的数组)?
标签: c# unit-testing attributes