Інтеграційне тестування перевіряє коректність взаємодії між компонентами мобільного додатка — модулями, сервісами, базами даних та зовнішніми API. На відміну від модульних тестів, які ізолюють кожен компонент, інтеграційні тести виявляють помилки на стиках: несумісність форматів даних, збої при передачі параметрів та некоректну обробку відповідей від сервера. За даними Martin Fowler, 2018, інтеграційні тести охоплюють до 40% критичних дефектів, пропущених модульними перевірками, та забезпечують впевненість у стабільності системи перед релізом.
Головне
Інтеграційне тестування — це етап перевірки програмного забезпечення, на якому оцінюється коректність взаємодії між окремими модулями або підсистемами додатка. Якщо модульні тести перевіряють кожен компонент ізольовано, то інтеграційні тести збирають ці компоненти разом і перевіряють, як вони працюють у зв’язці. Типові сценарії включають передачу даних між мережевим рівнем та репозиторієм, запис у базу даних через ORM та обробку відповідей від сторонніх API.
У контексті мобільної розробки інтеграційні тести охоплюють взаємодію між UI-шаром, бізнес-логікою та джерелами даних. Наприклад, тест може перевірити, що після натискання кнопки «Увійти» додаток надсилає запит на сервер, отримує токен та зберігає його в локальному сховищі. Така перевірка підтверджує, що ланцюг компонентів працює без збоїв.
За даними звіту World Quality Report 2023, компанії, які регулярно застосовують інтеграційне тестування, зменшують кількість виробничих інцидентів на 35% порівняно з проєктами, що покладаються лише на модульні тести. Це робить інтеграційні перевірки обов’язковим елементом стратегії забезпечення якості в комерційній розробці.
Мобільні додатки складаються з багатьох взаємопов’язаних компонентів: мережевих запитів, локальних баз даних, push-повідомлень, системних сервісів та сторонніх SDK. Кожен з цих компонентів розробляється окремо, але в часі виконання вони обмінюються даними в реальному часі. Інтеграційне тестування виявляє дефекти, які неможливо виявити при ізольованій перевірці модулів.
До числа типових проблем, що виявляються інтеграційними тестами, належать невідповідність типів даних між API та моделлю додатка, помилки серіалізації JSON, некоректна обробка мережевих таймаутів та збої при паралельному доступі до бази даних через Room або Core Data. Без інтеграційних перевірок такі дефекти потрапляють у виробництво та проявляються лише у реальних користувачів.
Дослідження Google Testing Blog (2021) показує, що вартість виправлення дефекту, виявленого на етапі інтеграційного тестування, в 5 разів нижча, ніж після релізу. Це пояснюється тим, що на ранніх стадіях розробник має повний контекст помилки і може виправити її без термінового циклу hotfix. Інвестування часу в написання інтеграційних тестів окупається зниженням витрат на супровід та підвищенням довіри користувачів.
Існує три основні підходи до організації інтеграційних тестів: Big Bang, Bottom-Up та Top-Down. Вибір стратегії залежить від розміру проєкту, архітектури додатка та доступності компонентів на момент написання тестів. Кожен підхід має свої переваги та обмеження, які важливо враховувати при плануванні тестового покриття.
Big Bang — підхід, коли всі компоненти системи з’єднуються одночасно, після чого виконується загальний тестовий прогін. Цей метод простий у реалізації: не потрібно писати заглушки чи емулювати окремі модулі. Однак при виявленні помилки складно визначити, який саме компонент став її джерелом. Big Bang виправданий у невеликих проєктах з простою архітектурою, де кількість модулів не перевищує п’яти.
Bottom-Up — стратегія, коли інтеграційне тестування починається з низькорівневих компонентів: бази даних, мережевого рівня, системних сервісів. Після перевірки кожного рівня тести поступово підключають вищостоячі модулі — репозиторії, Use Case-класи та ViewModel. Головна перевага — раннє виявлення дефектів у фундаментальних шарах додатка, що знижує ризик каскадних помилок на пізніх етапах розробки.
Top-Down — підхід, коли тестування починається з компонентів верхнього рівня — UI-екранів та навігації, а нижчостоячі модулі імітуються за допомогою заглушок або моків. Це дозволяє перевіряти користувацькі сценарії до того, як серверна частина або база даних повністю реалізовані. Top-Down особливо корисний при паралельній розробці клієнтської та серверної частин, коли бекенд ще не готовий до реальної інтеграції.
Для інтеграційного тестування мобільних додатків використовується набір спеціалізованих інструментів, які діляться на три категорії: бібліотеки для емуляції серверів, фреймворки для роботи з базами даних та засоби перевірки системних сервісів. Вибір конкретного інструмента залежить від платформи — Android або iOS — та технологічного стеку проєкту.
Розглянемо практичні приклади інтеграційних тестів для Android та iOS. Для платформи Android використовуємо MockWebServer разом з JUnit, для iOS — XCTest з бібліотекою OHHTTPStubs. Обидва приклади перевіряють сценарій отримання даних від API та їх збереження в локальному репозиторії.
Цей тест перевіряє, що Retrofit-запит до емульованого сервера повертає коректний JSON, а репозиторія перетворює відповідь у доменну модель. MockWebServer перехоплює запит та повертає заданий JSON, після чого тест порівнює очікуваний результат з фактичним.
class UserRepositoryTest {
private val mockServer = MockWebServer()
@Before
fun setup() {
mockServer.start()
}
@Test
fun fetchUser_returnsCorrectData() {
val json = "{ \`"id\`": 1, \`"name\`": \`"Alice\`" }"
mockServer.enqueue(MockResponse()
.setBody(json)
.setResponseCode(200))
val repository = UserRepository(
createRetrofit(mockServer.url("/").toString()))
val user = repository.fetchUser(1)
assertEquals(1, user.id)
assertEquals("Alice", user.name)
}
@After
fun tearDown() {
mockServer.shutdown()
}
}
Для iOS аналогічний тест використовує OHHTTPStubs для перехоплення URL-запитів. Бібліотека підмінює відповідь сервера на рівні системного фреймворку URL Loading System, що дозволяє тестувати будь-яку мережеву бібліотеку — URLSession, Alamofire або Moya.
import XCTest
import OHHTTPStubs
import OHHTTPStubsSwift
class UserRepositoryTests: XCTestCase {
func testFetchUser_returnsCorrectData() {
stub(condition: isPath("/users/1")) { _ in
return HTTPStubsResponse(
jsonObject: ["id": 1, "name": "Alice"],
statusCode: 200,
headers: nil
)
}
let repository = UserRepository()
let expectation = expectation(description: "fetch user")
repository.fetchUser(id: 1) { user in
XCTAssertEqual(user.id, 1)
XCTAssertEqual(user.name, "Alice")
expectation.fulfill()
}
waitForExpectations(timeout: 2.0)
}
}
Ефективне інтеграційне тестування вимагає дотримання набору практик, які підвищують стабільність тестів та знижують витрати на їх підтримку. Ізолюйте зовнішні залежності: використовуйте бази даних в пам’яті замість виробничих екземплярів та емулюйте сторонні API за допомогою бібліотек-заглушок. Це усуняє недетерміновані збої, спричинені доступністю мережі або станом зовнішніх сервісів.
Підтримуйте незалежність тестів: кожен інтеграційний тест повинен працювати ізольовано, без залежності від результатів інших тестів. Використовуйте анотації @Before та @After в JUnit або setUp та tearDown в XCTest для підготовки та очищення тестового середовища. Це запобігає взаємному впливу тестів та спрощує діагностику помилок.
Охоплюйте крайові випадки: інтеграційні тести мають перевіряти не лише успішні сценарії (happy path), але й обробку помилок — таймаути, HTTP-коди 4xx та 5xx, порожні відповіді, некоректний JSON. За даними Google Testing Blog (2022), 60% виробничих інцидентів пов’язані з некоректною обробкою крайових випадків, які не були покриті тестами.
Часто задавані питання
Модульні тести перевіряють один клас або функцію ізольовано, замінюючи залежності заглушками. Інтеграційні тести перевіряють взаємодію кількох реальних компонентів — наприклад, мережеве з’єднання та базу даних одночасно.
Прогін інтеграційних тестів зазвичай займає від 2 до 15 хвилин залежно від кількості тестів та складності середовища. Для великих проєктів рекомендується розбивати тести на паралельні завдання в CI-системі, щоб скоротити загальний час перевірки перед мерджем.
В першу чергу інтеграційні тести пишуть для мережевого рівня, бази даних та системних сервісів — сповіщень, камери, геолокації. API-запити до бекенду та операції з локальним сховищем дають найбільший ROI, оскільки ці компоненти найчастіше стають джерелом регресій.
Для одного екрана достатньо модульних тестів ViewModel та UI-тестів. Інтеграційні тести для одного екрана виправдані лише якщо екран взаємодіє з кількома джерелами даних — наприклад, об’єднує відповіді від двох різних API або записує дані одночасно в мережу та локальну базу даних.
Інтеграційні тести запускаються при кожному pull request в CI-пайплайні та перед основними релізами. Рекомендується також запускати повний набір інтеграційних тестів вночі (nightly build), щоб виявити дефекти, пов’язані зі змінами в залежностях або тестовому середовищі.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також