有没有办法使用 MSTests 顺序运行单元测试?

Posted

技术标签:

【中文标题】有没有办法使用 MSTests 顺序运行单元测试?【英文标题】:Is there a way to run unit tests sequentially with MSTests? 【发布时间】:2010-12-05 09:57:06 【问题描述】:

我在一个主要是单线程、单用户的应用程序中工作。 到处都有一些工作线程,它们只使用线程安全的对象和类。单元测试实际上是在测试具有多个线程(为测试显式创建)的测试,并且它们测试良好。

在测试非线程安全的业务对象和子系统时,VSTS 单元测试会失败。它们不是线程安全的也没关系,这就是应用程序使用它们的方式。

但是 MS 测试的“每个 TestMethod 一个线程”方法会害死我们。我不得不在许多单元测试类中实现对象锁,以确保测试一个接一个地运行(我并不关心顺序,但我不能让两个测试方法在同时)。

代码如下:

[TestClass]
public class TestSomeObject

   static object turnStile = new object();
...
   [TestMethod]
   public void T01_TestThis()
   
      lock(turnStile)
      
      .. actual test code
      
   

   [TestMethod]
   public void T02_TestThat()
   
      lock(turnStile)
      
      -- actual test code
      
   


是否有更好/更优雅的方式让测试按顺序运行?

【问题讨论】:

看来您在所有测试中都在重用某个对象的实例? 是的,基本上。有时是数据库,有时是单例 - 在应用程序中使用 我终于使用了有序的测试方法。它运作良好。然而,我花了很长时间让它与 NAnt 构建一起工作。 在构建中运行有序测试列表需要在 MSTest 调用块中使用 /testmetadata 和 /testlist 开关。关于这些的文档是粗略的,使用一种描述。我到处搜索“MSTest /testmetadata /testlist”的例子,但没有效果。然而,诀窍很简单,我觉得有必要将它回馈给社区,以防其他人遇到同样的问题。 1.编辑测试元数据文件(扩展名为.vsmdi),a 既然你声称这是 unit-testing 通过你的标签,你应该模拟/存根你的依赖关系,特别是不是线程安全的依赖关系 所以,简短的回答是:不。没有办法做到这一点,因为单元测试彼此之间不可靠,你能负担得起改变你的测试,以便在每次测试中创建和销毁这样的实例吗? 【参考方案1】:

使用Ordered Test

测试 > 新测试 > 有序测试

【讨论】:

好东西。我知道必须有一种更简单的方法...... :) 使用有序测试时如何指定 .runsettings 文件?具体来说,我需要使用 .runsettings 中指定的参数访问 TestContext。 @ajhuddy:听起来像是一个新的 Stack Overflow 问题的好人选。首先搜索以确保您的问题尚未被提出和回答,并在编写新问题时参考此问题。 “基于 MSTest V2 的测试不能在有序测试中使用”出现在窗口底部。不错。【参考方案2】:

您可以使用播放列表

右击测试方法->添加到播放列表->新建播放列表

然后您可以指定执行顺序

【讨论】:

我觉得这是这个问题的最佳答案。 工作得最好,而且很容易在一分钟内完成设置。【参考方案3】:

有一个“有序测试”的概念,您可以在其中按顺序列出测试。它更倾向于确保一定的顺序,但如果 B 不等待 A 完成,我看不出这怎么可能。

除此之外,很遗憾您的测试相互干扰。每个测试都可以使用 Setup / TearDown 方法,这样就可以将测试彼此隔离。

【讨论】:

不幸的是,MSTest 在同一个应用程序域中运行所有测试,使得测试首先可能相互干扰。【参考方案4】:

您可以为每个测试执行特别要求一个互斥锁,无论是在您想要序列化的特定测试中,还是为一个类中的所有测试(共享相同互斥锁字符串的任何测试)。

对于整个测试类,您可以像这样使用 TestInitialize 和 TestCleanup 属性:

private readonly Mutex testMutex = new Mutex(true, "MySpecificTestScenarioUniqueMutexString");

[TestInitialize]
public void Initialize()

    testMutex.WaitOne(TimeSpan.FromSeconds(1));


[TestCleanup]
public void Cleanup() 
    testMutex.ReleaseMutex();

要明确这不是测试的功能,任何锁定结构都应该有效。在这种情况下,我使用的是系统提供的互斥锁: https://msdn.microsoft.com/en-us/library/system.threading.mutex(v=vs.110).aspx

【讨论】:

您好,您能详细说明一下吗?例如,我需要澄清这个“......任何共享相同的互斥字符串”。此外,您声明 testMutex Private ReadOnly 但在初始化和清理中您正在使用 FileTestMutex... thx 您好!参考不匹配是一个错字,我已经修复它。我还添加了指向 Mutex 类的链接以进行说明。 Mutex 是 Microsoft 提供的锁定结构,它使用系统范围的字符串进行锁定,因此您希望字符串对于每个您想要序列化的事物集都是唯一的,这可能是每个测试或不同的整个测试类。如果您将字符串复制/粘贴到任何地方,那么每次使用它都会被序列化。另请注意上面的“OrderedTest”建议,如果它适合您,这可能是一个更好的主意。 Mutex(或其他手动锁定)方法很复杂。 我无法使用有序测试,因为我使用的是 MSTest v2。我试图使用您的 Mutex 方法,这看起来很简单,但我一直遇到 AbandonedMutex 异常,TestCleanup 是否应该在其他线程能够进入之前运行并释放互斥锁?【参考方案5】:

我终于使用了有序的测试方法。效果很好。

但是,我花了很长时间让它与 NAnt 构建一起工作。 在构建中运行有序的测试列表需要在 MSTest 调用块中使用 /testmetadata 和 /testlist 开关。 关于这些的文档是粗略的,使用一种描述。我到处搜索“MSTest /testmetadata /testlist”的例子,但没有效果。

不过,诀窍很简单,我觉得有必要将其回馈给社区,以防其他人遇到同样的问题。

    编辑测试元数据文件(扩展名为 .vsmdi),并添加一个新列表 到测试列表(左侧树中的第一个节点 窗格。给它起你想要的名字,例如“SequentialTests”。 如果您在 MSTest 调用中使用了 /testcontainer 开关,请将其移除。 为 MSTest 添加一个开关 -> /testmetadata: 为 MSTEst 添加一个开关 /testlist:SequentialTests(或您使用的任何名称)

然后 MSTest 只运行您创建的测试列表中列出的测试。

如果有人有更好的方法,我想听听!

【讨论】:

【参考方案6】:

我使用了有序的测试,也很容易在 jenkins 上配置它们,只需使用命令

MSTest /testcontainer:"orderedtestfilename.orderedtest" /resultsfile:"testresults.trx"

【讨论】:

以上是关于有没有办法使用 MSTests 顺序运行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法控制 Codeception 中的测试顺序?

有没有办法在 Create React App 应用程序中按顺序运行笑话测试?

有没有办法用 Jest 顺序运行一些测试?

有没有办法在 Quarkus 单元测试中回滚事务?

有没有办法批量处理 Karma - Angular 单元测试?

有没有办法开始只与更改代码相关的单元测试?