XCTest или Swift Testing ?

Возможно ты писал тесты с помощью XCTest и задумался о переходе на более современный подход. Swift Testing имеет как общие черты с XCTest, так и различия.

Данная глава включает в себя:

  1. Сранение функций и методов
  2. Сравнение XCT* с макросами
  3. Сравнение поддерживаемых типов данных
  4. Рекомендации по миграции из XCTest и недостатки Swift Testing

Сравнение функций

Сравнение функций

Тесты в XCTest — это любой метод начинающийся со слова test. Напротив, в Swift Testing ты указываешь атрибут @Test, исключая неоднозначность в намерениях. Библиотека тестирования поддерживает больше вариантов функций: ты можешь использовать не только методы, которые принадлежат этому типу данных, но и глобальные методы, а так же методы помеченные ключевым словом static. В отличии от XCTest, Swift Testing подерживает трейты, чтобы указать информацию или добавить определенное поведение к типу данных или отдельным функциям.

В конце концов Swift Testing использует другой подход для конкурентного выполнения тестов: под капотом используется Structured Concurrency и поддерживаются физические устройства как iPhone или Apple Watch.

Сравнение XCT* с макросами

Взгляни на таблицу сравнения:

Картинка сравнения

Сравнение результатов очень различаются в старом и новом подходах.

XCTest использует концепт различных проверок начинающихся с префикса XCAssert*.
Swift Testing имеет другой подход — существует только 2 макроса #expect и #require.

Картинка сравнения 2

Вместо объявления множества различных проверок достаточно использовать операции сравнения языка Swift в этих макросах. Например, используй 2 знака равно == для проверки равенства или оператор больше чем > для сравнения 2 значений.

Картинка сравнения 3

Кроме этого, ты можешь использовать оператор ! (восклицательный знак) для противоположной проверки.

Сравнение поддерживаемых типов данных

Сравнение типов

Говоря о типах данных, следует напомнить что XCTest поддерживает только классы, которые наследуются от XCTestCase. В Swift Testing ты можешь использовать стуктуры, акторы и классы. По возможности используй структуры, посколько они соответствуют value семантики и позволяют избегать ошибок с общим состоянием.

К каждому типу данных неявно применяется атрибут @Suite. Если ты хочешь задать отображаемое имя или использовать трейт, то в таком случае ты можешь применить атрибут @Suite.

Для выполнения логики перед каждым запуском в XCTest используется метод setUp(..). Аналогичным способом в Swift Testing используются инициализаторы, которые могут быть помечены ключевым словом async и/или throws. Для добавления логики после выполнения теста или типа данных ты можешь использовать деинициализатор deinit {...}.

deinit можно использовать в акторах и классах.
~Copyable структуры не поддерживаются Swift Testing, хоть и имеют возможность использовать deinit.

struct C: ~Copyable {
  deinit {}

  @Test("Ownership for sheep")
  func sheepOwner() async throws {
	  #expect(UnicodeScalar(0x1F411) == "\u{1F411}")
  }
}

❌ Ошибка — Noncopyable структуры не поддерживаются в Swift Testing.

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

Миграция из XCTest

Если ты задумался переписать тесты на современный подход, то у меня хорошие новости — тесты XCTest и Swift Testing могут существовать в одном таргете, поэтому ты можешь мигрировать постепенно и без создания нового таргета. Если класс XCTest содержит только 1 метод, рекомендую сделать его глобальной функцией с атрибутом @Test, это нормальная практика в Swift Testing. При именовании тестов больше не нужен префикс test.

Следует упомянуть о важном недостатке в Swift Testing. В новой библиотеке отсутствует возможность создания автоматизации пользовательского интерейса XCUIApplication, а так же тесты производительности XCTMetric.

important

XCUIApplication и XCTMetric не поддерживаются в Swift Testing.

Помимо этого, продолжай использовать XCTest если тесты написаны на Objective-C, поскольку Swift Testing не поддерживает Objective-C совсем. В конце концов избегай вызова функций из XCTest в функция Swift Testing или вызов макросов в XCTest.

important

Не вызывай функции из XCTest в Swift Testing.
Не вызывай макросы из Swift Testing в классах XCTest.
Не смешивай старый подход в новом и наоборот.