首页 > 解决方案 > NUnit TestFixture 和 TestCase

问题描述

我必须用 NUnit 编写一些集成测试来测试 HTTP 端点。这意味着应该在所有测试方法之间共享 URL。

[TestFixture("http://my.endpoint.com")]
public class TestSuiteOne
{
   [TestCase(10, 20, Expected = 30)]
   [TestCase(20, 30, Expected = 50)]
   public int TestA(int a, int b, HttpResponseMessage sut)
   {
        // AAA.
   }

   [TestCase("XXX", "YYY", Expected = "ABC")]
   public int TestA(string a, string b, HttpResponseMessage sut)
   {
        // AAA.
   }
}

要获得来自测试套件属性的每个测试运行的 SUT 值,我知道两个选项:

选项 A(从类属性中读取 SUT)


public abstract class TestSuiteBase
{
    protected(string endpoint)
    {
        Sut = endpoint;
    }

    protected HttpResponseMessage Sut { get; }
}

[TestFixture("http://my.endpoint.com")]
public class TestSuiteOne : TestSuiteBase
{
   public TestSuiteOne(string endpoint) : base(endpoint)
   {
   }

   [TestCase(10, 20, Expected = 30)]
   [TestCase(20, 30, Expected = 50)]
   public int TestA(int a, int b)
   {
        // act (read content/response code/headers/etc); Making a call I do not consider as act.
        var actual = Sut.DoSomething();

        // assert
   }

   [TestCase("XXX", "YYY", Expected = "ABC")]
   public int TestA(string a, string b)
   {
        // act (read content/response code/headers/etc); Making a call I do not consider as act.
        var actual = Sut.DoSomething();

        // assert
   }
}

选项 B(拦截测试方法调用)

public class MyTestCase: TestCaseAttribute
{
    public MyTestCase(params object[] args) : base(Resize(args))
    {
    }

    // I do resize before method call because VS Test Adapters discover tests to show a list in the test explorer
    private static object[] Resize(params object[] args)
    {
        Array.Resize(ref args, args.Length + 1);
        args[args.Length - 1] = "{response}";

        return args;
    }
}

public abstract class TestSuiteBase
{
   [SetUp]
   public void OnBeforeTestRun()
   {
       var ctx = TestContext.CurrentContext;

       var args = ctx.Test.Arguments;

       // Making a call I do not consider as act.
       args[args.Length - 1] = MakeCallAndGetHttpResponseMessage(args);
   }
}

[TestFixture("http://my.endpoint.com")]
public class TestSuiteOne : TestSuiteBase
{
   [MyTestCase(10, 20, Expected = 30)]
   [MyTestCase(20, 30, Expected = 50)]
   public int TestA(int a, int b, HttpResponseMessage sut)
   {
        // act (read content/response code/headers/etc); Making a call I do not consider as act.
        var actual = sut.DoSomething();

        // assert
   }

   [MyTestCase("XXX", "YYY", Expected = "ABC")]
   public int TestA(string a, string b, HttpResponseMessage sut)
   {
        // AAA.
   }
}

有没有更方便的方法可以将来自 TestFixture 的值与 TestCase 结合起来?

标签: c#unit-testingtestingnunit

解决方案


由于您将端点字符串放在 上TestFixtureAttribute,我将假设

  1. 您想与夹具中的所有测试用例共享它。
  2. 不想与任何其他灯具共享它。

您的示例中唯一缺少的是一个构造函数,它将接受您提供的参数。只需添加类似...

public TestSuiteOne(string url)
{
     Sut = endpoint;
}

只要您创建Sut只读属性或字段,您的任何测试用例都无法更改它,无论它们是按顺序运行还是并行运行。

您提供的两个选项对我来说似乎都过于复杂,至少在您解释问题的范围内。第一个最接近这个答案。

当然,您完全有可能对网站做其他事情,这会导致并行(甚至顺序)测试相互干扰。不要那样做。:-) 说真的,共享驱动程序与共享字符串完全不同,但这是一个不同的问题。

IMO,顺便说一下,你和你的团队应该习惯一个或另一个测试框架。您提到的生命周期问题并不是 NUnit 和 xUnit 之间唯一的细微差别!


推荐阅读