Как xUnit запускает тесты: последовательно или параллельно
Что проверяют
Знаете ли вы, что xUnit параллелит тесты из коробки, и понимаете ли единицу параллелизма: тестовую коллекцию. Следом обычно спрашивают, как изолировать тесты, которые делят базу или статическое состояние.
Как отвечать
Базовое правило для v2 и v3: внутри одной коллекции тесты идут последовательно, разные коллекции идут параллельно. По умолчанию каждый тестовый класс сам себе коллекция, поэтому методы одного класса выполняются друг за другом, а классы между собой параллельно. Параллельный прогон нескольких сборок по умолчанию выключен.
Инструменты управления:
[Collection("Db")]: классы с одним именем коллекции попадают в одну коллекцию и перестают идти параллельно друг с другом;[CollectionDefinition("Db", DisableParallelization = true)]: коллекция выполняется отдельно, после параллельных;[assembly: CollectionBehavior(DisableTestParallelization = true)]или"parallelizeTestCollections": falseвxunit.runner.json: параллелизм выключается целиком;maxParallelThreads: по умолчанию равен числу логических ядер, можно задать число или множитель вроде2.0x;parallelAlgorithm:conservative(по умолчанию) запускает не больше тестов, чем потоков,aggressiveполезен для тестов, которые в основном ждутawait.
Для общих ресурсов есть фикстуры: IClassFixture<T> создаёт объект один раз на класс, ICollectionFixture<T> один раз на коллекцию. Экземпляр тестового класса создаётся заново на каждый тест, поэтому поля между тестами не текут.
Для сравнения: NUnit и MSTest по умолчанию не параллелят, там это включается атрибутами [Parallelizable] и [Parallelize].
Где спотыкаются
Говорят, что xUnit по умолчанию всё запускает последовательно. Это неверно, и именно отсюда берутся «плавающие» тесты после добавления нового класса, который трогает ту же базу.
Считают, что [Theory] с десятком наборов данных по умолчанию выполняется параллельно. Строки одной теории живут в одном классе и идут по очереди.
Выключают параллелизм для всей сборки из-за двух тестов с общей базой. Правильнее собрать их в отдельную коллекцию с фикстурой, а остальное оставить параллельным.