测试夹具继承并忽略基本测试夹具

Jon*_*and 8 nunit

我有一组基本测试,用于测试接口的多个实现.我对其进行模拟的方法是创建一个带有[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
}
Run Code Online (Sandbox Code Playgroud)

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

public class ConcreteThingTests :  BaseTests
{
    public override ITestableThing GetConcrete()
    {
        return new ConcreteThing();
    }
}
Run Code Online (Sandbox Code Playgroud)

这很好用,因为我在一个地方完成了所有实现的所有测试,子类只是指定了实现.

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

因此,我的测试结果总是被一组忽略测试混乱,虽然这不是什么大问题,但我认为可能有一个更好的模式,避免不得不忽略测试.

那么,我实现测试夹具继承错了吗?

Lee*_*Lee 15

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

public abstract class BaseTests
{
}
Run Code Online (Sandbox Code Playgroud)

  • 我认为这是一个来自命名空间之外的抽象类.当我将我的作为摘要复制到它所使用的同一个项目时,但不是当它们在不同的项目中时.Nunit版本也必须相同 (2认同)

Ter*_*røm 5

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

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

为此,可以使用带有类工厂方法的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;
    }
}
Run Code Online (Sandbox Code Playgroud)