查找构建和测试运行中缺少的单元测试





5.00/5 (1投票)
查找测试结果中未显示的单元测试。
引言
很多时候,我们运行了数千次测试,却发现**只有几百次真正完成**,或者**数百次测试缺失**。问题来自**破坏测试执行系统**的测试。大多数情况下,我们无法在开发环境中重现这个问题,但在构建环境中,测试会持续破坏测试运行程序。
背景
我们发现,在**XAML构建**和**VNext构建**中使用**_mstest_**或_**vstest.console.exe**_时会出现此问题。下面,我将测试称为“breaking
”,这意味着测试导致异常,从而破坏了测试执行程序,这与测试失败不同。有时,必须在构建服务器上以正确的设置运行失败的测试才能重现问题。
查找问题
首先需要做的就是**找到导致问题的测试**。
测试可能由于许多地方的问题而“breaking
”,包括TestInitialize
、ClassInitialize
等。因此,我们需要某种方法来跟踪哪个测试有问题以及它在哪里有问题。
- 在我看来,**最快捷的方法是让测试记录到一个滚动尾部日志文件**,该文件在测试的不同部分更新。大多数情况下,我们在
ClassIntialize
和TestInitialize
或TestMethod
本身中看到问题。Log4Net
可以有效地创建这些日志。这应该能够**显示破坏系统的测试**以及它在哪里中断。我们跟踪以下内容的开始和结束AssemblyInitialize
ClassInitailize
TestInitialize
TestCleanup
ClassCleanup
AssemblyCleanup
- 您还可以查看测试运行的_.trx_文件,以查看**最后运行的测试**,它将是最后一个
UnitTestResult
元素。这只会显示最后成功运行的测试,但是您必须弄清楚**下一个测试是什么**。
如果您选择了**方案1**,您可以查看日志,应该能够找到导致执行程序中断的问题测试。如果它在ClassInitialize
中失败,您应该会看到Class Initialize Started,但不会看到Class Initialize Finished。
如果您选择**方案2**,则需要更进一步才能获得**测试按运行顺序排列的列表**。由于您应该**知道在破坏系统测试之前运行的最后一个测试**,您可以简单地找出**下一个测试应该是哪个**。使用Reflection
,您可以获取测试程序集中具有TestMethod
属性的方法。下面是我们运行的UnitTest
,用于获取按运行顺序排列的测试列表。
[TestClass]
public class Utilities
{
[TestMethod]
[TestCategory("Utility")]
public void GetTestMethods()
{
foreach (var type in System.Reflection.Assembly.GetExecutingAssembly().GetTypes())
{
foreach (var method in type.GetMethods())
{
foreach (var attrib in method.CustomAttributes.Select(c => c.ToString()))
{
if (attrib.ToString().Contains("TestMethodAttribute"))
{
Console.WriteLine(method.Name);
break;
}
}
}
}
}
}
运行测试后,可以通过打开**测试资源管理器**,然后单击GetTestMethods
并单击**输出**来查看结果。这将显示**按运行顺序排列的测试列表**,只需找到_.trx_文件中列出的最后一个测试,然后找出下一个测试。
关于修复测试的一句话
我不想深入探讨如何修复您的测试,但我认为我会添加我们遇到的**最常见的场景**。
- **断言对象为空**。如果对象不为
null
,但对象的属性为null
,则测试会失败但可以,但是如果您尝试访问null
对象的属性,则会中断。 - 我们的大多数问题都来自**异步调用中的竞争条件**,这可能是异步方法在测试完成后返回,或者在异步结果上使用某些
Assert
方法,其中评估发生在返回结果之前。