如何使用vstest.console.exe在一个测试失败时停止测试?

5

我有一个批处理文件,其中包含多个以类似下面形式定义的测试。

vstest.console.exe Test.dll /Settings:"test.runsettings" /Tests:"t1,t2,t3,t4,t5"

测试按照t1到t5的顺序运行。但是,如果有任何一个测试失败,我希望停止vstest。使用vstest.console.exe是否可能实现这一点?
另外,我的test.runsettings内容如下:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <MSTest>
    <ForcedLegacyMode>true</ForcedLegacyMode> 
      <KeepExecutorAliveAfterLegacyRun>true</KeepExecutorAliveAfterLegacyRun> 
  </MSTest>
</RunSettings>

我已经查看了runsettings文档,似乎没有针对这种情况的标志/属性。

1
我在 TFS 构建服务器的 MSDN 上询问了这个问题,但没有得到答案。不过我不知道 vstest。 - user1228
1
你让我想起了MSDN。我在msdn上发布了同样的问题,希望他们会有答案,然后我可以在这里发布官方的看法。我认为应该提供一个实现此功能的标志。但是文档中没有任何信息。 - Bangonkali
无法相信这是不可能的。 - thepirat000
3个回答

3

如果要运行的测试数量很少,就像你的示例一样,你可以将其拆分为多个vstest.console.exe运行,并在批处理中检查ERRORLEVEL。如果ERRORLEVEL不为0,则表示有测试失败,你可以退出批处理。

vstest.console.exe Test.dll /Settings:"test.runsettings" /Tests:"t1"
IF ERRORLEVEL 1 GOTO exit
vstest.console.exe Test.dll /Settings:"test.runsettings" /Tests:"t2"
IF ERRORLEVEL 1 GOTO exit
...

:exit

这是一个很好的建议!如果@lukbl的建议有效,我会尝试它,然后再尝试这个。我计划实现两者来看哪个更快。此外,在每个DLL或测试套件基础上实现ErrorLevel将是一个很好的想法。 - Bangonkali

2
如果可以的话,您可以引入具有清理、初始化方法和TestContext属性的测试基类。在清理方法中,您将检查测试是否失败,并通过在TestInitialize中触发Assert.Fail,不允许在此之后通过任何其他测试。
[TestClass]
public class BaseTest
{
    private static bool _failAllTests;
    public TestContext TestContext { get; set; }

    [TestInitialize]
    public void InitializeMethod()
    {
        if (_failAllTests)
        {
            Assert.Fail("Fail all tests");
        }
    }

    [TestCleanup]
    public void CleanUpMethod()
    {
        if (TestContext.CurrentTestOutcome == UnitTestOutcome.Failed)
        {
            _failAllTests = true;
        }
    }
}
[TestClass]
public class UnitTest1 : BaseTest
{
    [TestMethod]
    public void TestMethod1()
    {
        Assert.Fail("TestMethod1 failed!");
    }
    [TestMethod]
    public void TestMethod2()
    {
        Assert.IsTrue(true, "TestMethod2 passed!");
    }
}

0
除了lukbl的答案之外,您还可以在整个程序集范围内执行相同的操作,因此,如果您有多个测试类,则在vstest.console.exe运行时(例如,如果您多次调用它),您将对测试进行全局管理。
根据您如何使用vstest.console(或mstest),需要注意。如果您在多个测试代理之间进行负载平衡,则每个测试代理都将运行自己的vstest.console.exe,并且因此将具有其自己的程序集级别值,因此会话管理将受到在同一代理上运行的测试组的限制。假设这种方法将为您提供使用命令运行的整个测试集的管理: vstest.console.exe /filter: tests.dll
这意味着,无论您的session_failed变量的范围是类范围还是程序集范围,如果您最终使用不同的vstest.console.exe调用从同一类运行不同的测试,则会失去变量值或控制。
话虽如此,对于多类测试场景,有一个简单的方法:
[TestClass]
public static class TestSettings
{
    public static bool SessionTestsFailed = false;

    [AssemblyInitialize]
    public static void runsBeforeAnyTest(TestContext t)
    {
        TestSettings.SessionTestsFailed = false;
    }
}

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

    [TestInitialize()]
    public void MyTestInitialize()
    {
        if (TestSettings.SessionTestsFailed)
            Assert.Fail("Session failed, test aborted");
    }

    [TestCleanup]
    public void MyTestFinalize()
    {
        if (TestContext.CurrentTestOutcome != UnitTestOutcome.Passed)
            TestSettings.SessionTestsFailed = true;
    }

    [TestMethod]
    public void test11()
    {
        Console.WriteLine("test11 ran");
        Assert.Fail("fail the test");
    }

    [TestMethod]
    public void test12()
    {
        Console.WriteLine("test12 ran");
        Assert.Fail("fail the test");
    }
}

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

    [TestInitialize()]
    public void MyTestInitialize()
    {
        if (TestSettings.SessionTestsFailed)
            Assert.Fail("Session failed, test aborted");
    }

    [TestCleanup]
    public void MyTestFinalize()
    {
        if (TestContext.CurrentTestOutcome != UnitTestOutcome.Passed)
            TestSettings.SessionTestsFailed = true;
    }

    [TestMethod]
    public void test21()
    {
        Console.WriteLine("test21 ran");
        Assert.Fail("fail the test");
    }

    [TestMethod]
    public void test22()
    {
        Console.WriteLine("test22 ran");
        Assert.Fail("fail the test");
    }

这里有一个简单的方法,可以使用正则表达式匹配和 Visual Studio 的替换全部功能,一次性更新所有测试初始化方法(如果它们的签名相同):

查找:

(\s*)public void MyTestInitialize\(\)(\s*)(\r*\n)(\s*){(\r*\n)

替换:

$1public void MyTestInitialize()$3$4{$1\tif (TestSettings.SessionTestsFailed) Assert.Fail("Session failed, test aborted");

对于TestFinalize()也是类似的处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接