控制Visual Studio中单元测试的执行顺序

iGa*_*nja 68 c# unit-testing visual-studio-2012

好的,我已经完成了关于这个的好消息.我有一系列单元测试,它们调用一个静态类,一旦初始化,就会设置不能(或我不希望)改变的属性.

我的问题是我无法强制执行测试运行的设置顺序.如果可以的话,我可以运行它们,因为静态属性将以可靠的方式设置,我可以断言它们,但不幸的是,Microsoft.VisualStudio.TestTools.UnitTesting框架只是以看似随机的顺序运行它们.

所以,我发现这个http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.priorityattribute.aspx在备注部分说"测试系统不使用此属性.它用于自定义目的的用户." 咦?那有什么用呢?他们是否希望我编写自己的测试包装器来利用这个神奇的属性(如果我想要达到那种程度的努力,我可以轻松地自己编写...)

所以,足够的咆哮; 最重要的是,有没有办法控制我的单元测试运行的顺序?

[TestMethod]
[Priority(0)]
Run Code Online (Sandbox Code Playgroud)

似乎没有用,这是有道理的,因为微软说它不会.

另外,请不要评论"违反隔离".TestClass隔离了我正在测试的内容,而不是单独的TestMethods.无论如何,每个测试都可以独立运行,它们不能以随机顺序一起运行,因为没有办法拆除静态类.

哦,我也知道"有序测试".

HB *_*AAM 109

您可以使用播放列表

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

执行顺序将在您将其添加到播放列表时,但如果您想要更改它,则您拥有该文件

在此输入图像描述

  • @Jrd在Visual Studio 2015中,事情发生了一些变化.在Solution Explorer中,右键单击单元测试项目,单击Add> OrderedTest.这样做会为项目添加一个新文件.当您打开此文件时,您可以单击项目中的测试方法并将其添加1次或更多次以进行此测试. (27认同)
  • 刚刚在VS2015中试过这个,看起来播放列表不会影响执行顺序.相反,它们按声明方法的顺序运行. (17认同)
  • 这对构建服务器不起作用 (4认同)

小智 52

将您的测试合并为一个巨大的测试将起作用.为了使测试方法更具可读性,您可以执行类似的操作

[TestMethod]
public void MyIntegratonTestLikeUnitTest()
{
    AssertScenarioA();

    AssertScenarioB();

    ....
}

private void AssertScenarioA()
{
     // Assert
}

private void AssertScenarioB()
{
     // Assert
}
Run Code Online (Sandbox Code Playgroud)

实际上你提出的问题可能是你应该提高实现的可测试性.

  • 这可能有效,但它违背了单元测试的目的。单元测试的想法是将部分分解成块以进行快速测试 - 而不是将它们粉碎在一起, (3认同)
  • 合并测试是一种公平的方法,但是如果列表中的第一个测试方法未通过断言,则其他任何方法都不会执行。考虑到OP测试策略固有的顺序依赖性,这可能不是问题。 (2认同)

Mat*_*rix 10

我没有看到有人提到ClassInitialize属性方法.属性非常简单.

创建使用[ClassInitialize()]or [TestInitialize()]属性标记的方法,以准备运行单元测试的环境的各个方面.这样做的目的是建立一个运行单元测试的已知状态.例如,您可以使用[ClassInitialize()][TestInitialize()]方法复制,更改或创建测试将使用的某些数据文件.

创建使用[ClassCleanup()]or [TestCleanUp{}]属性标记的方法,以在运行测试后将环境返回到已知状态.这可能意味着删除文件夹中的文件或将数据库返回到已知状态.例如,在测试订单输入应用程序中使用的方法之后,将库存数据库重置为初始状态.

  • [ClassInitialize()]用于ClassInitialize在类中运行第一个测试之前运行代码.

  • [ClassCleanUp()]用于ClassCleanup在类中的所有测试运行后运行代码.

  • [TestInitialize()]用于TestInitialize在运行每个测试之前运行代码.

  • [TestCleanUp()]用于TestCleanup在每个测试运行后运行代码.

  • 还有AssemblyInitialize和AssemblyCleanup,它们分别在每个测试运行的开始和结束时运行. (2认同)

Tia*_*eal 8

如您现在所知,纯粹主义者说禁止运行有序测试。对于单元测试来说可能是正确的。MSTest和其他单元测试框架不仅用于运行纯单元测试,而且还用于UI测试,完全集成测试。也许我们不应该将它们称为单元测试框架,或者应该根据需要使用它们。无论如何,这就是大多数人所做的事情。

我正在运行VS2015,并且必须以给定的顺序运行测试,因为我正在运行UI测试(Selenium)。

优先级 -完全不执行任何操作 测试系统未使用此属性。提供给用户用于自定义目的。

orderedtest-它可以工作,但我不建议这样做,因为:

  1. 一个orderedtest文本文件,该文件按执行顺序列出了您的测试。如果更改方法名称,则必须修复该文件。
  2. 在类内部遵守测试执行顺序。您无法命令哪个类首先执行其测试。
  3. 一个orderedtest文件绑定到配置,Debug或推出
  4. 您可以有多个orderedtest文件,但是给定的方法不能在其他orderedtest文件中重复。因此,对于Debug,不能有一个orderedtest文件,对于Release,则不能有另一个。

该线程中的其他建议很有趣,但是您失去了在Test Explorer上关注测试进度的能力。

您将得到纯粹主义者会建议的解决方案,但实际上是可行的解决方案:按声明顺序排序

MSTest执行程序使用一个互操作程序来设法获取声明顺序,并且该技巧将起作用,直到Microsoft更改测试执行程序代码为止。

这意味着首先声明的测试方法要在第二个声明的方法之前执行,依此类推。

为了使您的生活更轻松,声明顺序应与“测试资源管理器”中显示的字母顺序匹配。

  • A010_FirstTest
  • A020_SecondTest
  • 等等
  • A100_TenthTest

我强烈建议您使用一些古老且经过测试的规则:

  • 使用10步,因为稍后您将需要插入测试方法
  • 避免在测试编号之间使用足够大的步骤来重新编号测试编号
  • 如果您运行的测试超过10个,请使用3位数字为您的测试编号
  • 如果您运行的测试超过100个,请使用4位数字为您的测试编号

很重要

为了按照声明顺序执行测试,必须在“测试资源管理器”中使用“全部运行”

假设您有3个测试类(在我的案例中是针对Chrome,Firefox和Edge的测试)。如果选择给定的类并右键单击“运行选定的测试”,则通常从执行最后声明的方法开始。

再次,如我之前所说,声明的顺序列出的顺序应该匹配,否则您很快就会遇到大麻烦。


Hon*_*tan 6

正如评论者已经指出的那样,依赖于其他测试的测试指出了设计缺陷.然而,有办法实现这一目标.正如先前问的问题回答了这里,你可以创建有序的单元测试,这基本上是一个单一的测试容器,以确保测试序列.

这是MSDN的指南:http://msdn.microsoft.com/en-us/library/ms182631.aspx

  • @RicardoPieper您描述的是测试夹具设置.只要每个测试都进行设置和拆卸(清理),完全可以根据需要进行测试(毕竟这是测试夹具的目的).我的答案是关于根据变异的夹具状态或先前测试的结果来警告测试,因为那样你就可以获得链失败,并且你很难找到首先出现的问题.它指向纠缠不清的逻辑,过于紧密耦合.只要每次测试都以新设备开始,就可以了 - 否则要小心. (3认同)
  • 你能解释一下它是如何设计缺陷的吗?我知道某些东西应该在执行时起作用,但是,例如,在我的测试中,我必须启动一个SQLite数据库(从头开始)并将一些数据放入其中,然后我必须抓住这些数据.如果数据库不存在,我无法获取数据.此外,测试类型要求我使用新的数据库.我应该在每次测试中删除并重新创建数据库吗? (2认同)

Tod*_*les 5

既然您已经提到了Visual Studio测试框架提供的Ordered Test功能,那么我将忽略它。您似乎也意识到,为了测试此静态类而要完成的工作是一个“坏主意”,因此我将其忽略。

相反,让我们关注您实际上可能如何保证测试按所需顺序执行。一个选项(由@gaog提供)是“一种测试方法,许多测试函数”,可以在标有TestMethod属性的单个函数中按所需顺序调用测试函数。这是最简单的方法,唯一的缺点是第一个失败的测试函数将阻止其余任何测试函数执行

根据您对情况的描述,这是我建议您使用的解决方案。

如果您的粗体部分有问题,您可以利用内置的数据驱动的测试功能来完成隔离测试的有序执行。它比较复杂,感觉有点脏,但是可以完成工作。

简而言之,您定义了一个数据源(例如CSV文件或数据库表),该数据源控制着运行测试所需的顺序以及实际上包含测试功能的功能的名称。然后,您可以将该数据源挂接到数据驱动的测试中,使用顺序读取选项,并按照所需的顺序执行功能,作为各个测试。

[TestClass]
public class OrderedTests
{
    public TestContext TestContext { get; set; }

    private const string _OrderedTestFilename = "TestList.csv";

    [TestMethod]
    [DeploymentItem(_OrderedTestFilename)]
    [DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", _OrderedTestFilename, _OrderedTestFilename, DataAccessMethod.Sequential)]
    public void OrderedTests()
    {
        var methodName = (string)TestContext.DataRow[0];
        var method = GetType().GetMethod(methodName);
        method.Invoke(this, new object[] { });
    }

    public void Method_01()
    {
        Assert.IsTrue(true);
    }

    public void Method_02()
    {
        Assert.IsTrue(false);
    }

    public void Method_03()
    {
        Assert.IsTrue(true);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的示例中,我有一个名为TestList.csv的支持文件,该文件被复制到输出中。看起来像这样:

TestName
Method_01
Method_02
Method_03
Run Code Online (Sandbox Code Playgroud)

您的测试将按照您指定的顺序执行,并且处于正常的测试隔离状态(即,如果一个测试失败,其余测试仍将执行,但共享静态类)。

以上只是一个基本的想法,如果我要在生产中使用它,我将在运行测试之前动态生成测试函数名称及其顺序。也许可以利用发现的PriorityAttribute和一些简单的反射代码来提取类中的测试方法并对其进行适当排序,然后将该顺序写入数据源。