Иерархические методы "OneTimeSetUp" - PullRequest
0 голосов
/ 06 ноября 2018

Хорошо, у меня есть несколько тестов, которые я пишу для тестирования API. Каждый раз, когда мне нужно запустить эти тесты, мне сначала нужно войти в 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 голосов
/ 07 ноября 2018

Вот один из возможных способов достижения этого.

Если у вас есть общий базовый класс (как это звучит из вашего описания), вы можете создать защищенного ленивца, чтобы получить свой токен, как показано в примере ниже

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. Одноэлементный объект также можно использовать вместо статического в приведенном выше примере, если у вас нет общего базового класса для ваших приборов.

0 голосов
/ 06 ноября 2018

Вы можете сгруппировать свои тестовые классы в те же пространства имен, а затем добавить дополнительный класс, помеченный атрибутом SetupFixture. Это будет запускать код инициализации только один раз для каждого пространства имен. (Не путать с атрибутом «TestFixtureSetUp», который помечен как устаревший со времен NUnit v3. Спасибо Чарли за ваш комментарий, я изначально перепутал его.)

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 Выписан.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...