Как правильно тестировать View внутри ViewController?

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

Ответ

Да, тестировать View в контексте ViewController можно и нужно. Подход зависит от цели теста.

1. Unit-тесты (логика и состояние): Используйте XCTest для проверки корректности настройки, данных и реакций View.

import XCTest
@testable import YourApp

class ViewControllerTests: XCTestCase {
    func test_viewController_loadsAndConfiguresLabel() {
        // Given
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let sut = storyboard.instantiateViewController(
            withIdentifier: "MyViewController"
        ) as! MyViewController

        // When: Загружаем view иерархию (вызывает viewDidLoad)
        _ = sut.view

        // Then: Проверяем состояние элементов View
        XCTAssertNotNil(sut.titleLabel)
        XCTAssertEqual(sut.titleLabel.text, "Expected Title")
        XCTAssertFalse(sut.actionButton.isHidden)
    }
}

2. UI-тесты (взаимодействие и навигация): Используйте XCUITest для симуляции действий пользователя.

import XCTest

class AppUITests: XCTestCase {
    func test_buttonTap_showsAlert() {
        let app = XCUIApplication()
        app.launch()

        app.buttons["ActionButton"].tap()

        XCTAssertTrue(app.alerts["Success Alert"].exists)
    }
}

3. Snapshot-тесты (визуальная регрессия): Используйте библиотеки (например, PointFreeco/swift-snapshot-testing) для фиксации корректного внешнего вида.

import SnapshotTesting
import XCTest

func test_viewController_snapshot() {
    let vc = MyViewController()
    assertSnapshot(of: vc, as: .image(on: .iPhone13))
}

Best Practices:

  • Изоляция: По возможности тестируйте View отдельно от ViewController (например, кастомные UIView).
  • Избегайте тестирования деталей рендеринга ОС (точные оттенки, системные анимации).
  • Используйте моки и стабы для зависимостей (сети, базы данных).
  • Загружайте view иерархию (_ = sut.view) перед проверкой outlet-свойств.