Эквивалент NUnit для управления состоянием теста JUnit с @ Before / @ After - PullRequest
0 голосов
/ 22 декабря 2018

Я из мира Java и в основном использовал JUnit, и теперь у меня есть некоторые проблемы с выражением некоторых аспектов тестов с помощью NUnit 3. В JUnit каждый тест создает свой собственный экземпляр класса теста, поэтому вполне допустимо создать несколькоПеременные экземпляра в тестовом классе, настройте их в методе @Before, метод теста и помощники могут свободно обращаться к этим переменным, не беспокоясь о том, что они будут перезаписаны другими параллельными тестами, а @After красиво разбивает тестовые данные.С NUnit это не работает, и методы SetUp и TearDown кажутся бесполезными в этом случае, потому что экземпляр тестового прибора повторно используется между вызовами метода (ов) теста, поэтому поля класса тестового прибора могут (и являются) перезаписыватьсяпри каждом вызове тестового метода (в моем классе есть несколько тестовых методов, и каждый из них генерирует несколько тестовых случаев, поэтому в одном тестовом прогоне есть несколько десятков вызовов).

Я не знаю, какобойти эту проблему.В моем сценарии настройка создаст временную папку, которая будет использоваться в качестве рабочей папки для следующего контрольного примера.Снос затем удалил бы временную папку, очистив все промежуточные файлы, созданные проверенным методом.Но теперь, когда SetUp создает и сохраняет путь временной папки в поле экземпляра (чтобы его можно было прочитать с помощью тестовой логики и несколько сложных утверждений и верификаторов), значение такого поля перезаписывается при выполнении тестовых примеров, выполняемых параллельно.Я рассмотрел несколько подходов:

  • реализует IDisposable, который будет представлять контекст каждого теста, и заключать его в using в каждом методе теста - мне не нравится эта идея,потому что мне не нравится идея использования IDisposable в качестве чего-то еще, кроме инструмента управления ресурсами и объединения IDisposable с using для имитации настраиваемых / разрушающих запахов, как злоупотребление этой конкретной языковой функцией,

  • создать метод, который принимает делегата для фактической логики теста и который вызывает пользовательские методы SetUpTestCase / TearDownTestCase.Метод будет вызывать set up, затем тестировать делегат, а затем завершать работу.Что мне не нравится в этом подходе, так это то, что он плохо работает с методами тестирования, которые принимают параметры - каждому набору методов, параметризованных определенным образом, потребуется соответствующий тип делегата.Также кажется, что это противоречит духу NUnit и способу описания методов тестирования с атрибутами - в конце концов, почему основная логика моего теста должна быть делегирована чему-либо?Разве метод [Test] или [TestCase] не должен быть реальным тестом?

  • может быть, есть какой-то способ использовать более сложные аспекты NUnit, такие как действия или некоторые обратные вызовы / триггеры / что угодно,Я просто слишком неопытен, чтобы увидеть это.Что мне особенно не хватает, так это способ передачи данных из настроенного метода (например, путь к созданной им временной папке) в следующий метод тестирования.Я не могу использовать для этого поля экземпляра, и я не знаю, существует ли какая-либо структура «тегов», которая передавала бы специфичные для теста данные между методами, вызываемыми на разных этапах жизненного цикла теста?

Обычно атрибуты SetUp и TearDown кажутся мне совершенно бесполезными, если они не могут настроить тестовый набор без немедленной перезаписи его результата другим параллельным прогоном тестового набора.Чего мне здесь не хватает?

Как я могу реализовать такое для каждого теста поведение при настройке / отключении с помощью NUnit?Что я делаю не так или что мне не хватает?

1 Ответ

0 голосов
/ 22 декабря 2018

Как вы установили, класс TestFixture создается один раз перед вызовом OneTimeSetUp;затем для каждого теста запускается набор SetUp, Test и TearDown;и, наконец, OneTimeTearDown.

Если вы хотите, чтобы тесты выполнялись параллельно (что не является значением по умолчанию), вы должны указать Параллельный атрибут .Независимо от того, делаете ли вы это или нет, неплохо бы, чтобы ваши тесты были написаны независимо, поэтому они не конфликтуют друг с другом - их необходимо структурировать.

AAA (Arrange, Act, Assert)шаблон является распространенным способом структурирования модульных тестов для тестируемого метода.Если ваши тесты должны выполняться параллельно, то поля TestFixture не подходят для хранения информации, которая может конфликтовать между параллельными тестами, так же, как это не подходит для многопоточного класса.

I 'Рекомендуется использовать закрытый метод в TestFixture для настройки временной папки - для этого потребуется какой-то способ предоставления уникального имени папки, чтобы параллельные тесты не взаимодействовали - возможно, используйте Guid или CallerMemberName как часть папкиname и вернуть имя папки.

Этот метод следует вызывать из части Arrange теста.И вам понадобится попытка ... наконец обернуть оставшуюся часть теста, чтобы убедиться, что папка разрушена.Или вы могли бы пойти с вашей идеей IDisposable - я не думаю, что с этим что-то не так: весь смысл в том, чтобы гарантировать приведение в порядок ресурсов (как управляемых, так и неуправляемых), когда что-то выходит за рамки.

Ваше второе предложение делегата также было бы хорошо, если бы вы использовали лямбда-выражения, а не строго определенные делегаты - лямбда-выражение может захватывать переменные из содержащей области.

...