"仅在条件满足时运行方法"图案

时间:2017-11-21 08:11:52

标签: c# attributes decorator

我有一个方法

using Microsoft.VisualStudio.TestTools.UnitTesting; // using visual studio's test framework

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

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

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

为了解决这个问题,我添加了一个public class BaseTestClass,我从ATestClass派生了ATestClass,并在public bool isTheSoftwareInstalledOnTheMachine() { // stuff } 中添加了一个:

ATestClass

和我"装饰"来自[TestMethod] public void ATestMethod() { if (isTheSoftwareInstalledOnTheMachine()) { // stuff } } 的所有内部测试范围如下:

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

我觉得这太可怕了。我希望能够写出类似的内容:

[characterizer]

但我不知道是否允许一个人定义" custom" characterizer'第(我甚至不知道对他们说对的话。)如果是,那会是最好的设计吗? (我听说过装饰模式,但我不知道我是否可以在我的上下文中使它足够通用,因为我可能需要将该条件用于许多其他测试类。)无论如何,我将如何继续String(describing: self)' s?

4 个答案:

答案 0 :(得分:1)

如果您定义自己的属性,则必须检查以确保其存在。您不能指望您的框架猜测属性的用途。

但我想你甚至不需要一个属性来做到这一点。您可以通过将逻辑放在测试方法中来忽略测试:

[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();
}

如果未满足该编码,则根本不会生成测试用例。

答案 1 :(得分:1)

我知道你正在使用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);
        }
    }
}

答案 2 :(得分:0)

如果计算机上安装的软件是任何测试通过的要求,并且任何一个测试失败意味着整个套件失败,那么如果安装了软件,为什么还要在多个测试中检查? ?如果没有安装软件,只需写一个测试失败并抛出一个有用的异常。类似的东西:

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

答案 3 :(得分:0)

对于Nunit 2.6,对HimBromBeere的答案进行一些细微的修改对我来说非常有效。测试用例显示为已忽略。

[TestCaseSource("ProvideTestcases")]
public void MyTest() { /* ... */ }

private static IEnumerable<TestCaseData> ProvideTestcases()
{
    if(RunIfTheSoftwareInstalledOnTheMachine)
        yield return new TestCaseData().Ignore();
}