9

我有一组用于测试接口的多个实现的基本测试。我对此建模的方法是创建一个带有 [Ignore] 属性的基本文本装置。

[TestFixture]
[Ignore]
public class BaseTests
{
     // Use your imagination for the actual name
     public virtual ITestableThing GetConcrete()
     {
         return null;
     }

     // All of my unit tests here
}

然后我为每个接口实现写一个子类:

public class ConcreteThingTests :  BaseTests
{
    public override ITestableThing GetConcrete()
    {
        return new ConcreteThing();
    }
}

这很好用,因为我将所有实现的所有测试都放在一个地方,并且子类只指定实现。

问题是我必须将 [Ignore] 属性放在基类上,否则 NUnit 将尝试运行测试(并失败)。

正因为如此,我的测试结果总是被一组 Ignored 测试弄得乱七八糟,虽然这没什么大不了的,但我认为可能有一个更好的模式来避免忽略测试。

那么,我是否实现了测试夹具继承错误?

4

2 回答 2

18

如果基类被标记为抽象,NUnit 测试运行器似乎会忽略它:

public abstract class BaseTests
{
}
于 2014-03-25T14:45:03.507 回答
5

您通常会在具体测试类而不是基类上设置测试属性。

由于您似乎为多个类测试相同的功能,您可以跳过整个测试层次结构并将要测试的具体类注入该测试基类。

要使用 NUnit 做到这一点,您可以使用带有类工厂方法的 TestCaseSource 属性作为参数。可以在此处找到一个示例:如何将动态对象传递给 NUnit TestCase 函数?

为您的特定情况编写一些代码,可能如下所示:

/// <summary>
/// Earlier known as your BaseTests class
/// </summary>
[TestFixture]
public class TestOfConcreteImplementationsOfInterface
{
    [TestCaseSource("CreateConcretes")]
    [Test]
    public void VerifyImplementations(IWhatever thing)
    {
        int input = 42;
        int result = thing.DoSomething(input);
        Assert.That(result, Is.EqualTo(input));
    }

    /// <summary>
    /// Factory method for the concrete classes.  If you want this in a seperate class, you can do that too using the 
    /// ctor public TestCaseSourceAttribute(Type sourceType, string sourceName);
    /// </summary>
    public IEnumerable<IWhatever> CreateConcretes
    {
        get
        {
            yield return new A();
            yield return new B();
        }
    }
}

public interface IWhatever
{
    int DoSomething(int x);
}

public class A : IWhatever
{
    public int DoSomething(int x)
    {
        return x;
    }
}

public class B : IWhatever
{

    public int DoSomething(int x)
    {
        return x;
    }
}
于 2013-08-03T16:10:13.610 回答