Конкурентный и последовательный запуск тестов

Serialized — тип данных позволяющий контролировать конкурентное или последовательное выполнение тестов.

По умолчанию

Тесты выполняются конкурентно (concurrency) по умолчанию. Это возможно благодаря использованию метода withTaskGroup(of:returning:body:) из раздела Structured concurrency[1]. Количество одновременно запущенных тестов управляется в runtime.

Сохранили много времени

Последовательное выполнение

Для последовательного выполнения теста с множеством аргументов используй трейт .serialized:

@Test(.serialized, arguments: Food.allCases)
func prepare(food: Food) {
    // ...
}

Последовательный запуск

Функция prepare(food:) будет выполнять последовательно каждый из аргументов.

Атрибут @Suite принимает такой же трейт:

@Suite(.serialized)
struct IsolationConfirmation {
  @Test(arguments: IsolatedData.allCases)
	func executeWith(data: IsolatedData) async throws {
		// Выполнение этой функции будет последовательным,
        // аргумент за аргументом.
	}

  @Test
  func uniqlyExecute() async throws {
    // Данная функция не будет запущена до тех пор,
    // пока executeWith(data:) выполняется. Прежде
    // чем начать выполнение необходимо дождаться
    // завершение предыдущей.
  }
}

extension IsolationConfirmation {
	@Suite
	struct NonIsolatedData {
		// Все функции в этом типе данных будут
        // выполняться последовательно
	}
}

В примере выше ты применил трейт .serialized и все функции с атрибутом @Test, включая вложенные типы данных, будут выполняться последовательно.

important

Трейт .serialized применяется рекурсивно. При применении к атрибуту @Suite, любая функция с атрибутом @Test будет выполнятья последовательно, включая вложенные типы данных.

Применение трейта не влияет на выполнение других типов данных и тестов в других файлах. Эффект будет только на там, где указан .serialized.

Другим примером, когда применение трейта не имеет эффекта, послужит пример ниже:

@Test
func findPalindrome() {
	let word: String = "Madam"
	let result = word.filter(\.isLetter).lowercased().reversed()

	#expect(word.lowercased() == String(result))
}

Применение трейта к одиночной глобальной функции не имеет никакого эффекта. Ты получишь предупреждение, если функция не имеет параметров, а атрибут @Test не имеет аргументов.

⚠️ Trait '.serialized' has no effect when used with a non-parameterized test function

Если ты передал флаг --no-parallel в команду swift test, то применение трейта не будет иметь эффекта, посколько ты глобально отключил конкурентное выполнение.

note

На момент выхода книги не существует обратного трейта, который выполняет тесты конкурентно.


[1]Познакомится с новым подходом можно в моей книге Structured Concurrency не магия.