简体   繁体   English

NUnit 测试夹具和测试用例

[英]NUnit TestFixture and TestCase

I have to write some integration tests with NUnit that should test HTTP endpoints.我必须用 NUnit 编写一些集成测试来测试 HTTP 端点。 This means that URL should be shared across all test methods.这意味着 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.
   }
}

To get SUT value on each test run that comes from test suite attribute I know two options:要在来自测试套件属性的每个测试运行中获取 SUT 值,我知道两个选项:

Option A (read SUT from class property)选项 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
   }
}

Option B (intercept test method call)选项 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.
   }
}

Is there any more convenient way how to combine value that comes from TestFixture with TestCase?有没有更方便的方法如何将来自 TestFixture 的值与 TestCase 结合起来?

Since you placed the endpoint string on the TestFixtureAttribute , I will assume由于您将端点字符串放在TestFixtureAttribute ,我将假设

  1. That you want to share it with all the test cases in the fixture.您想与夹具中的所有测试用例共享它。
  2. That you do not want to share it with any other fixtures.那你希望与任何其它灯具分享。

The only thing missing in your example is a constructor that will accept the argument you are providing.您的示例中唯一缺少的是一个构造函数,它将接受您提供的参数。 Just add something like...只需添加类似...

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

So long as you make Sut a readonly property or field, none of your testcases will be able to change it, whether they are run sequentially or in parallel.只要您将Sut设为只读属性或字段,您的任何测试用例都无法更改它,无论它们是按顺序运行还是并行运行。

Both the options you provide seem overly complex to me, at least insofar as you have explained the problem.您提供的两个选项对我来说似乎都过于复杂,至少就您对问题的解释而言。 The first one is closest to this answer.第一个最接近这个答案。

Of course, it's entirely possible that you might do other things with the web site, which would cause parallel (or even sequential) tests to interfere with one another.当然,您完全有可能对网站做其他事情,这会导致并行(甚至顺序)测试相互干扰。 Don't do that.不要那样做。 :-) Seriously, sharing a driver is entirely different from sharing a string, but that's a different question. :-) 说真的,共享驱动程序与共享字符串完全不同,但这是一个不同的问题。

IMO, by the way, you and your team should get used to one test framework or another.顺便说一句,IMO,您和您的团队应该习惯一个或另一个测试框架。 The lifecycle issue you mention is not the only subtle difference between NUnit and xUnit!您提到的生命周期问题并不是 NUnit 和 xUnit 之间唯一的细微差别!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM