Я пришел из мира Java и в основном использовал JUnit, и теперь у меня есть некоторые проблемы с выражением некоторых аспектов тестов с помощью NUnit 3. В JUnit каждый тест создает свой собственный экземпляр тестового класса, поэтому вполне допустимо создавать некоторые переменные экземпляра в тестовый класс, настройте их в @Before
методе, тестовый метод и помощники могут свободно обращаться к этим переменным, не беспокоясь о том, что они будут перезаписаны другими тестами, запущенными параллельно, и @After
аккуратно удаляет тестовые данные. С NUnit это не работает, и методы SetUp
и TearDown
в этом случае кажутся бесполезными, потому что экземпляр тестовой оснастки повторно используется между вызовами тестовых методов, поэтому поля класса тестовой оснастки могут (и перезаписываются) при каждом вызове тестовый метод (у моего класса есть несколько тестовых методов, и каждый из них генерирует несколько тестовых случаев, так что за один тестовый прогон приходится несколько десятков вызовов).
Я не знаю, как обойти эту проблему. В моем сценарии при настройке будет создана временная папка, которая будет использоваться в качестве рабочей папки для следующего тестового примера. После этого временная папка будет удалена, а все промежуточные файлы, созданные проверенным методом, будут удалены. Но теперь, когда SetUp
создает и сохраняет временный путь к папке в поле экземпляра (чтобы он мог быть прочитан тестовой логикой и несколько сложными утверждениями и верификаторами), значение такого поля перезаписывается параллельными тестами. Я рассмотрел несколько подходов:
реализовать
IDisposable
, который будет представлять контекст каждого теста, и заключить его вusing
в каждом методе тестирования - мне не нравится эта идея, потому что мне не нравится идея использованияIDisposable
как чего-то другого, кроме инструмента управления ресурсами и объединенияIDisposable
сusing
, чтобы имитировать запахи установки/сноса для меня, как злоупотребление этой конкретной языковой особенностью,создайте метод, который принимает делегат для фактической тестовой логики и вызывает пользовательские методы
SetUpTestCase
/TearDownTestCase
. Метод вызовет установку, затем проверит делегат, а затем разрушит. Что мне не нравится в этом подходе, так это то, что он плохо сочетается с методами тестирования, которые принимают параметры - каждому набору методов тестирования, параметризованному определенным образом, потребуется соответствующий тип делегата. Также это как-то противоречит духу NUnit и способу описания тестовых методов атрибутами — в конце концов, зачем кому-то делегировать основную логику моего теста? Разве метод[Test]
или[TestCase]
не должен быть фактическим тестом?возможно, есть какой-то способ использовать более продвинутые аспекты NUnit, такие как действия или некоторые обратные вызовы/триггеры/что-то еще, я просто слишком неопытен, чтобы увидеть это. Чего мне особенно не хватает, так это способа передачи данных из метода настройки (например, пути к созданной им временной папке) в следующий за ним тестовый метод. Я не могу использовать для этого поля экземпляра, и я не знаю, существует ли какая-либо структура «тегов», которая будет передавать специфичные для теста данные между методами, вызываемыми на разных этапах жизненного цикла теста?
Как правило, атрибуты SetUp
и TearDown
кажутся мне довольно бесполезными, если они не могут настроить тестовый пример без того, чтобы их результат был немедленно перезаписан другим параллельным тестовым набором. Что мне здесь не хватает?
Как я могу реализовать такой сценарий для каждого теста, поведение установки/снятия с ограниченной областью действия с помощью NUnit? Что я делаю не так, или что я упускаю?