Как происходит передача данных в тесты
Что проверяют
Знаете ли вы механизмы параметризации своего тестового фреймворка и умеете ли держать тестовые данные так, чтобы тесты оставались независимыми. Следом часто спрашивают, чем жизненный цикл тестового класса в xUnit отличается от NUnit.
Как отвечать
Разделите ответ на три источника данных:
- параметры теста: в xUnit это
[Theory]вместе с[InlineData]для констант,[MemberData]для статического свойства или метода и[ClassData]для отдельного класса, для типизации естьTheoryData<T>. В NUnit аналоги[TestCase],[TestCaseSource],[Values]и[Range], в MSTest[DataRow]и[DynamicData]; - общее окружение (фикстуры): в NUnit
[SetUp]выполняется перед каждым тестом,[OneTimeSetUp]один раз на класс. В xUnit таких атрибутов нет: класс создаётся заново на каждый тест, подготовка идёт в конструкторе, очистка вIDisposableилиIAsyncLifetime, а дорогие ресурсы вроде контейнера с базой разделяют черезIClassFixture<T>иICollectionFixture<T>; - данные объектов: вместо ручной сборки сущностей используют билдеры, AutoFixture для случайных значений и Bogus для правдоподобных. Зависимости подменяют через Moq или NSubstitute, чтобы тест получал ровно те ответы, которые нужны сценарию.
Для интеграционных тестов добавьте файлы с данными (JSON в проекте тестов, прочитанный в [MemberData]) и Testcontainers для настоящей базы.
Покажите, что следите за версиями: в NUnit 4 классические Assert.AreEqual переехали в ClassicAssert, основным стал Assert.That, а у xUnit актуальна третья версия.
Где спотыкаются
Не знают, что NUnit по умолчанию использует один экземпляр класса для всех его тестов. Поле, изменённое одним тестом, видит следующий, и порядок запуска начинает влиять на результат.
Кладут в [InlineData] то, что туда не помещается. Атрибуты принимают только константы, поэтому decimal, DateTime и объекты передаются через [MemberData] или TheoryData.
Тащат в тест огромный общий набор данных «на всё». Когда тест падает, непонятно, какое поле важно. Данные должны быть минимальными и лежать рядом со сценарием.