Тестирование асинхронного кода (XCTest)
Пишите асинхронные тесты с XCTest: помечайте тесты как async , используйте await и throws , проверяйте сбои и тайм-ауты, а также результаты структурированного параллелизма.
«Тестирование асинхронного кода (XCTest)» — бесплатный урок Swift Academy на CoddyKit. Это урок 3 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 3 уроков всего.
Асинхронные тесты: основы
XCTest поддерживает асинхронные тесты. Делайте тесты небольшими и детерминированными:
- Объявляйте асинхронные тесты и используйте ожидание
- Используйте выбрасывание ошибок и
do/catchдля обработки сбоев - Заменяйте задержки небольшими имитациями и заглушками
Успешный асинхронный случай
Сделайте тест асинхронным и вызовите SUT с ожиданием. Пишите обычные проверки, например XCTAssertEqual.
import XCTest
import Foundation
// System Under Test (SUT)
func fetchValue() async -> Int {
try? await Task.sleep(nanoseconds: 50_000_000)
return 42
}
final class AsyncBasicsTests: XCTestCase {
func testFetchValue_returns42() async {
let v = await fetchValue()
XCTAssertEqual(v, 42)
}
}Асинхронное выбрасывание ошибок и проверки
Используйте тесты с асинхронностью и выбрасыванием ошибок. Для конкретных ошибок перехватывайте их и сопоставляйте с образцом, чтобы намерение оставалось понятным.
import XCTest
enum NetError: Error { case offline }
func loadNumber(online: Bool) async throws -> Int {
try await Task.sleep(nanoseconds: 30_000_000)
if !online { throw NetError.offline }
return 7
}
final class AsyncThrowingTests: XCTestCase {
func testLoadNumber_success() async throws {
let n = try await loadNumber(online: true)
XCTAssertEqual(n, 7)
}
func testLoadNumber_offline_throws() async {
do {
_ = try await loadNumber(online: false)
XCTFail("Expected error")
} catch NetError.offline {
// expected
} catch {
XCTFail("Unexpected error: \\(error)")
}
}
}Параллельные результаты
Структурированное конкурентное выполнение легко тестировать: используйте async let и проверяйте итоговый результат. Делайте задержки очень короткими, чтобы избежать нестабильных тестов.
import XCTest
func compute(_ x: Int) async -> Int {
try? await Task.sleep(nanoseconds: 10_000_000)
return x * x
}
final class ParallelTests: XCTestCase {
func testParallel_asyncLet_sumsSquares() async {
async let a = compute(2)
async let b = compute(3)
let sum = await (a + b)
XCTAssertEqual(sum, 13) // 4 + 9
}
}Тестирование ограничения времени
Тестируйте ограничения времени, устраивая гонку операции и короткой задачи sleep. Используйте очень малые интервалы, чтобы тесты оставались быстрыми и стабильными.
import XCTest
enum TimeoutError: Error { case timedOut }
func withTimeout<T>(
seconds: Double,
operation: @escaping () async throws -> T
) async throws -> T {
try await withThrowingTaskGroup(of: T.self) { group in
group.addTask { try await operation() }
group.addTask {
try await Task.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
throw TimeoutError.timedOut
}
let first = try await group.next()!
group.cancelAll()
return first
}
}
final class TimeoutTests: XCTestCase {
func testTimeout_timesOutFast() async {
do {
_ = try await withTimeout(seconds: 0.01) {
try await Task.sleep(nanoseconds: 50_000_000) // slower than timeout
return "OK"
}
XCTFail("Expected timeout")
} catch TimeoutError.timedOut {
// expected
} catch {
XCTFail("Unexpected error: \\(error)")
}
}
}Ожидания (старый подход)
Для старых обратных вызовов по-прежнему используйте ожидания/ожидание завершения. Для нового кода отдавайте предпочтение асинхронным тестам.
import XCTest
// Legacy API with a completion handler
func legacyFetch(_ completion: @escaping (String) -> Void) {
Task { try? await Task.sleep(nanoseconds: 20_000_000); completion("done") }
}
final class ExpectationTests: XCTestCase {
func testLegacy_withExpectation() {
let exp = expectation(description: "legacy finishes")
legacyFetch { value in
XCTAssertEqual(value, "done")
exp.fulfill()
}
wait(for: [exp], timeout: 1.0)
}
}Современный стиль асинхронных тестов
Быстрая проверка: как лучше всего тестировать асинхронную функцию?
Итоги
Итоги: используйте асинхронные методы XCTest с ожиданием, проверяйте успешные и ошибочные пути, делайте задержки очень короткими, а ожидания оставляйте для старых обратных вызовов.
Часто задаваемые вопросы
Урок «Тестирование асинхронного кода (XCTest)» бесплатный?
Да — полный текст урока «Тестирование асинхронного кода (XCTest)» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 3 уроков всего.
Чему я научусь в уроке «Тестирование асинхронного кода (XCTest)»?
Пишите асинхронные тесты с XCTest: помечайте тесты как async , используйте await и throws , проверяйте сбои и тайм-ауты, а также результаты структурированного параллелизма. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Swift Academy?
Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 3.
Сколько времени занимает урок «Тестирование асинхронного кода (XCTest)»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Swift Academy?
Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Производитель и потребитель, конвейеры, тайм-ауты
- Переход от устаревших обратных вызовов и Combine к async/await
- Тестирование асинхронного кода (XCTest)