Розробка Unit-тестів для iOS-додатку (XCTest)

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Розробка Unit-тестів для iOS-додатку (XCTest)
Середній
~3-5 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Розробка Unit-тестів для iOS-додатку (XCTest)

Типова ситуація: ViewModel розростається до 500 рядків, у ній змішана бізнес-логіка, форматування даних та прямі виклики мережі. Додаєш нову фічу — ломається що-небудь у старому потоці. Откатуєш — знову працює, але причина неясна. Юнит-тесты на XCTest — це не про «покриття заради покриття», а про можливість рефакторити без страху.

Що тестуємо та як

Бізнес-логіка — головний пріоритет. ViewModel, Interactor, UseCase — все, де є ветвління if/switch, обчислення, трансформації даних. Протокол-ориєнтований підхід Swift робить це зручним: залежності інжектуються через протоколи, в тестах підміняються mock-об'єктами.

// Протокол сервісу
protocol UserServiceProtocol {
    func fetchUser(id: String) async throws -> User
}

// Mock для тестів
class MockUserService: UserServiceProtocol {
    var stubbedUser: User?
    var stubbedError: Error?

    func fetchUser(id: String) async throws -> User {
        if let error = stubbedError { throw error }
        return stubbedUser!
    }
}

// Тест
func testFetchUserSuccess() async throws {
    let mockService = MockUserService()
    mockService.stubbedUser = User(id: "1", name: "Test")
    let sut = UserViewModel(service: mockService)

    await sut.loadUser(id: "1")

    XCTAssertEqual(sut.user?.name, "Test")
    XCTAssertFalse(sut.isLoading)
}

Асинхронний код — другий за важливістю блок. Сучасний Swift з async/await тестується нативно: XCTest підтримує async тест-функції з iOS 15+ та Xcode 13+. Для Combine-based коду — XCTestExpectation + sink.

Граничні випадки — то, що реально падає в production: порожний масив, nil-значення, рядок з юнікодом, дата в іншому timezone. Не «happy path», а саме edge cases.

Архітектура, зручна для тестування

XCTest-тесты пишуться просто, коли архітектура припускає інверсію залежностей. MVVM з DI через ініціалізатор, Clean Architecture з UseCase — тестуються прямо. Singleton-и та статичні методи — нітавак. Якщо проект не використовує DI, частина роботи — рефакторинг перед написанням тестів.

Часта проблема: ViewModel звертається до UserDefaults напрямки, до Date() напрямки. Обидва потрібно обернути в протоколи та інжектувати — інакше тесты будуть залежати від системного стану та часу запуску.

Тестування Combine та async/await

// Combine: тестуємо Publisher
func testPublisherEmitsValue() {
    let expectation = expectation(description: "Value received")
    var cancellables = Set<AnyCancellable>()

    sut.statePublisher
        .dropFirst()  // пропускаємо початкове стан
        .sink { state in
            XCTAssertEqual(state, .loaded)
            expectation.fulfill()
        }
        .store(in: &cancellables)

    sut.loadData()
    waitForExpectations(timeout: 2)
}

CI-інтеграція

Тесты запускаємо на кожен PR через xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15'. Матриця версій iOS фіксується в GitHub Actions / Bitrise конфігурації. Code coverage репортуємо через Xcode Coverage Report або xcov gem. Ціль покриття — не 100%, а логіки: ViewModel/Interactor/UseCase повинні бути покриті на 80%+, UI — не трогаємо юнит-тестами.

Типові помилки в iOS unit-тестах

  • @testable import без флага -enable-testing у build settings — імпорт не працює в CI
  • Тесты, залежні від порядкуXCTest не гарантує порядок виконання, кожен тест має бути ізольований через setUp()/tearDown()
  • Реальні мережеві запити в тестах — тест стає нестійким та повільним. Завжди мокуємо через URLProtocol subclass або URLSession з кастомним URLSessionConfiguration

Процес роботи

Аудит існуючого коду → виділення тестуємих компонентів → при необхідності мінімальний рефакторинг для DI → написання тестів → інтеграція в CI. Репорт за покриттям після завершення.

Срок: 3–5 днів залежно від обсягу кодової бази та поточного рівня архітектурної ізольованості компонентів.