Какие существуют виды тестов в iOS и какие принципы покрытия кода?

«Какие существуют виды тестов в iOS и какие принципы покрытия кода?» — вопрос из категории Тестирование, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В iOS-разработке используются три основных уровня автоматизированных тестов, образующих тестовую пирамиду:

1. Unit-тесты (основа пирамиды):

  • Что тестируют: Изолированную бизнес-логику (функции, методы, классы).
  • Инструменты: XCTest, Quick/Nimble (BDD-стиль).
  • Пример:

    func test_UserModel_DecodesCorrectly() throws {
        // 1. Arrange (Подготовка)
        let json = """
        {
            "id": 42,
            "name": "John Appleseed"
        }
        """
        let data = Data(json.utf8)
    
        // 2. Act (Действие)
        let user = try JSONDecoder().decode(User.self, from: data)
    
        // 3. Assert (Проверка)
        XCTAssertEqual(user.id, 42)
        XCTAssertEqual(user.name, "John Appleseed")
    }
  • Принципы: Быстрые, изолированные (используют моки/стабы для зависимостей), покрывают множество сценариев (включая краевые случаи).

2. Integration-тесты (интеграционные):

  • Что тестируют: Взаимодействие нескольких модулей (например, сетевого слоя и слоя хранения).
  • Инструменты: XCTest.
  • Пример: Тест, который проверяет, что NetworkService корректно сохраняет данные в CoreDataManager.

3. UI-тесты (вершина пирамиды):

  • Что тестируют: Сквозные пользовательские сценарии.
  • Инструменты: XCUITest.
  • Особенности: Медленные, хрупкие, сложные в поддержке. Их должно быть меньше всего.

Ключевые принципы тестирования и покрытия:

  • F.I.R.S.T.: Тесты должны быть Fast (быстрыми), Isolated (изолированными), Repeatable (повторяемыми), Self-validating (самопроверяемыми), Timely (своевременными).
  • Фокус на поведение, а не на покрытие строк: Высокий процент покрытия (coverage) — не самоцель. Важно тестировать критическую бизнес-логику и сложные алгоритмы, а не геттеры/сеттеры.
  • Изоляция зависимостей: Зависимости (сеть, база данных, файловая система) должны быть заменены на протоколы с mock-реализациями в unit-тестах.
  • Структура теста (Arrange-Act-Assert): Четкое разделение этапов улучшает читаемость.
  • Не тестировать код платформы: Не пишите тесты для UIKit, Foundation или сторонних библиотек — предполагается, что они уже работают корректно.