是否有一个属性可以避免MSTest中的级联单元测试失败?

Jon*_*nny 5 c# attributes unit-testing

我试图更密切地遵循"每单元测试一个断言"的做法.它并非总是可行,但我确实发现它可用于精确定位错误.

例如,我可能有类似的东西:

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...
Run Code Online (Sandbox Code Playgroud)

问题是如果toTest的创建失败,那么所有其他单元测试也会失败.所以我们可以为此添加一些检查:

...

[TestMethod]
TestIsProperty1Setup() {
  if (toTest == null) Assert.Inconclusive()
  Assert.IsNotNull(toTest.Property1);
  // Maybe some more tests on Property1
}

...
Run Code Online (Sandbox Code Playgroud)

这将阻止级联故障并指出确切的问题.如果// 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]
}
Run Code Online (Sandbox Code Playgroud)

现在每个单独的测试都有更多重复的代码,更重要的是,Asserts必须在不同的测试之间保持同步,这意味着一个小的变化可以在许多单元测试中产生影响.

理想情况下,我希望有一个属性位于每个测试的顶部,只有在"先决条件"测试通过时才运行测试.它可能看起来像这样:

[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]
}
Run Code Online (Sandbox Code Playgroud)

单元测试现在非常简单 - 没有重复,并且保持测试与其"先决条件"同步现在是自动的.

有这样的事吗?或者是否有一个完全不同的功能,我可以使用它来获得相同的效果?

我知道将属性中的测试方法引用到另一个测试方法几乎肯定存在问题 - 您可能必须使用硬编码到方法名称的字符串(如果方法名称更改会发生什么,或者该方法不存在).我确信循环引用也存在潜在问题.但是,尽管存在所有这些问题,但有人必须解决这个问题.有人能指出我吗?

Bar*_*zKP 0

不鼓励测试之间的依赖性。问题的可能解决方案:如果在测试初始化​​方法中创建“toTest”失败(或使用普通断言),则抛出异常,那么我相信该组中的测试根本不会运行。您还可以使用静态类初始化(http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.classinitializeattribute.aspx)。但是,所有测试仍将被标记为失败。