分层的“ OneTimeSetUp”方法

时间:2018-11-06 19:19:50

标签: c# nunit

好的,我正在编写一些用于测试API的nunit测试。每当我需要运行这些测试时,我首先需要登录api以获取令牌。首先,这就是我编写OneTimeSetUp的方式。

因此,我登录时调用了OneTimeSetUp,共享字段存储了令牌,每个测试称为在api上测试不同端点的测试。

现在是问题所在。我们已经决定要对响应中的各个字段进行单独的测试,以便我们可以查看如果出现错误,确切地是什么(并且不会失败)。因此,我们将每个端点分为自己的测试。

现在,调用OneTimeSetUp,它登录并调用端点,存储结果,然后启动所有测试,以测试它们的一点点。

问题在于,登录需要花费时间,并且没有逻辑原因说明所有单独的测试不能仅仅使用相同的登录详细信息。有什么办法可以进一步细分测试/增加额外的测试水平?如果我们能够获得如下所示的测试结果,那就太好了

ApiTests <--- shared sign-in at this level - Endpoint 1 <--- call the endpoint at this level - Field 1 \ - Field 2 --- individual test results here - Field 3 / - Endpoint 2 <--- call the endpoint at this level - Field a \ - Field b --- individual test results here - Field c /

2 个答案:

答案 0 :(得分:1)

您可以将测试类分组到相同的名称空间中,然后添加一个用SetupFixture属性标记的附加类。每个名称空间仅运行一次初始化代码。 (不要与“ TestFixtureSetUp”属性混淆,该属性从NUnit v3开始就已过时。感谢Charlie的评论,我最初将其混为一谈。)

https://github.com/nunit/docs/wiki/SetUpFixture-Attribute

代码示例(与往常一样,您可以将每个类放到单独的代码文件中):

using System.Diagnostics;
using NUnit.Framework;

namespace Test
{
    [SetUpFixture]
    public class SharedActions
    {
        [OneTimeSetUp]
        public void SharedSignIn()
        {
            Debug.WriteLine("Signed in.");
        }

        [OneTimeTearDown]
        public void SharedSignOut()
        {
            Debug.WriteLine("Signed out.");
        }
    }

    [TestFixture]
    public class FirstEndpointTests
    {
        [Test]
        public void FirstEndpointTest()
        {
            Debug.WriteLine("Test for Endpoint A");
        }
    }

    [TestFixture]
    public class SecondEndpointTests
    {
        [Test]
        public void SecondEndpointTest()
        {
            Debug.WriteLine("Test for Endpoint B");
        }
    }
}

“全部调试”测试时,以下输出将显示在调试窗口中:

已登录。 测试端点A 测试端点B 退出。

答案 1 :(得分:0)

这是实现这一目标的一种可能方法。

如果您有一个通用的基类(从您的描述中听起来),则可以按照以下示例创建一个受保护的惰性类来获取令牌

public class ApiTestsBase
{
    protected static Lazy<string> TokenLazy = new Lazy<string>(() =>
                                                             {
                                                                 // Log in and get your API token
                                                                 Console.WriteLine("Logging into API to get token. You should only see this message on the first test that runs"); 
                                                                 return "DEADBEEF";
                                                             });

}

[TestFixture]
public class EndpointATests : ApiTestsBase
{
    private string GetResultFromEndPoint()
    {
        // Call endpoint with token from TokenLazy.Value
        Console.WriteLine($"Calling EndpointA with token {TokenLazy.Value}");
        return "PayloadA";
    }

    [Test]
    public void Test1()
    {
        var payload = this.GetResultFromEndPoint();
        // Assert things about payload
    }

}

[TestFixture]
public class EndpointBTests : ApiTestsBase
{
    private string GetResultFromEndPoint()
    {
        // Call endpoint with token from TokenLazy.Value
        Console.WriteLine($"Calling EndpointB with token {TokenLazy.Value}");
        return "PayloadB";
    }

    [Test]
    public void Test1()
    {
        var payload = this.GetResultFromEndPoint();
        // Assert things about payload
    }

}

现在我正在使用字符串类型,但是您可以使用与您的情况相关的任何请求,响应和令牌类型。我怀疑您还可以通过一些创造力将GetResultFromEndPoint调用移至基类,并使用抽象方法或属性填写端点特定的细节,但是您没有共享足够的代码让我尝试。

魔术关键字在static关键字中,这意味着每个应用程序域中只有一个实例。懒惰只是将创建推迟到第一次引用之前。如果您的测试用例需要长时间运行,因为您需要处理令牌更新,所以它会变得有些复杂,但是仍然可以使用类似的方式使用单例类来实现它,如果令牌寿命> x,该类会定期重新进行身份验证。如果您的灯具没有通用的基类,则在上述示例中,也可以使用单件对象代替静态对象。