“仅在满足条件的情况下才能运行一种方法”图案



我有一个方法

using Microsoft.VisualStudio.TestTools.UnitTesting; // using visual studio's test framework
[TestMethod]
public void ATestMethod()
{
    // stuff
}

来自public class ATestClass。该测试类运行两种类型的测试:

  • 测试要求在运行测试的计算机上安装某个软件
  • 可以免费运行的测试

为了处理此问题,我添加了一个public class BaseTestClass,从中我制作了ATestClass,在ATestClass中,我添加了A:

public bool isTheSoftwareInstalledOnTheMachine()
{
    // stuff
}

和我"装饰"了ATestClass的所有内部测试范围,如下:

[TestMethod]
public void ATestMethod()
{
    if (isTheSoftwareInstalledOnTheMachine())
    {
        // stuff
    }
}

我觉得这太可怕了。我宁愿能够写出类似的东西:

[TestMethod]
[RunIfTheSoftwareInstalledOnTheMachine]
public void ATestMethod()
{
    // stuff
}

,但我不知道是否允许有人定义"自定义" [characterizer]'S。(我什至不知道适合他们的词。)如果是,那是最好的设计吗?(我听说了装饰器的模式,但是我不知道我是否可以在上下文中使其足够通用,因为我可能需要在许多其他测试课程中使用该条件。)无论如何,我如何继续使用characterizer's?

我知道您正在使用VS测试框架,但是如果您可以更改为Nunit,则可以完成您想要的。

测试用例:

using NUnit.Framework;
[TestFixture]
public class MyAppTests
{
    [Test]
    [RunIfTheSoftwareInstalledOnTheMachine]
    public void ATestMethod()
    {
        // Executes if custom attribute is true, otherwise test case is ignored
    }
}

自定义属性:

using NUnit.Framework;
using NUnit.Framework.Interfaces;
public class TestHelper
{
    public static bool IsTheSoftwareInstalledOnTheMachine()
    {
        // Return state of software
        return true;
    }
}
public class RunIfTheSoftwareInstalledOnTheMachineAttribute : Attribute, ITestAction
{
    public ActionTargets Targets { get; private set; }
    public void AfterTest(ITest test) {}
    public void BeforeTest(ITest test)
    {
        if (!TestHelper.IsTheSoftwareInstalledOnTheMachine())
        {
            Assert.Ignore("Omitting {0}. Software is not installed on machine.", test.Name);
        }
    }
}

如果您定义自己的属性,则必须自行使用检查。您无法期望您的框架猜测该属性的用途。

但我想您甚至不需要一个属性来执行此操作。您可以通过将逻辑内部放置进行

来忽略测试。
[Test]
public void MyTest()
{
    if(!RunIfTheSoftwareInstalledOnTheMachine)
        Assert.Ignore("Test not run because no software was installed");
    // your actual test-code
}

另一种方法是使用Nunit提供的CategoryAttribute,您只能运行那些属于您提供的类别的测试:

[Test]
[Category("SoftwareInstalled")]
public void MyTest() { /* ... */ }

编辑:您也可以使用TestCaseAttribute使用特定方法,该方法在满足条件时返回TestCase

[TestCaseSource("ProvideTestcases")]
public void MyTest() { /* ... */ }
private static IEnumerable<TestCaseData> ProvideTestcases()
{
    if(RunIfTheSoftwareInstalledOnTheMachine)
        yield return new TestCaseData();
}

如果未达到编码,根本没有生成测试柜。

如果要在计算机上安装的软件是测试的任何的要求,并且任何一个测试失败意味着整个套件失败,那么为什么要打扰检查在多个测试中是否已安装软件?只需写一个测试即可失败,如果软件未安装并抛出有用的例外。类似:

[Test]
public void EnsureImportantSoftwareIsInstalled()
{
    if(!importantSoftwareIsInstalled)
    {
         Assert.Fail($"Software X must be installed for the tests in {nameof(MyTestClass)} to run, please install it");
    }
}

对于nunit 2.6,himbrombeere答案的略有变化对我来说很好。测试案例显示为忽略。

[TestCaseSource("ProvideTestcases")]
public void MyTest() { /* ... */ }
private static IEnumerable<TestCaseData> ProvideTestcases()
{
    if(RunIfTheSoftwareInstalledOnTheMachine)
        yield return new TestCaseData().Ignore();
}

最新更新