Розробка інтеграційних тестів для Flutter-додатків
Інтеграційні тести у Flutter запускаються на реальному пристрої або емуляторі. Додаток стартує повністю: Dart-рушій, Flutter Framework, ваш код. WidgetTester тут працює поверх реального рендерингу, не синтетичного. Саме тому інтеграційні тести знаходять те, що widget-тести пропускають: проблеми з навігацією між реальними Route, тайминги анімацій на конкретному залізі, поведінка при нестачі пам'яті.
Пакет integration_test
Сучасний спосіб — пакет integration_test з Flutter SDK (не сторонній, офіційний з Flutter 2.5). Він замінив застарілий flutter_driver.
pubspec.yaml:
dev_dependencies:
integration_test:
sdk: flutter
flutter_test:
sdk: flutter
Структура директорій:
integration_test/
app_test.dart
test_driver/
integration_test.dart # тільки для запуску через flutter drive
Запуск на підключеному пристрої:
flutter test integration_test/app_test.dart
Запуск у Firebase Test Lab або BrowserStack — через flutter build apk --target integration_test/app_test.dart + завантаження APK.
Що тестуємо та як
Типовий інтеграційний тест охоплює повний користувацький флоу: відкрив додаток → авторизувався → перейшов на екран каталогу → додав товар у кошик → оформив замовлення → побачив екран підтвердження.
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
testWidgets('Full checkout flow', (tester) async {
app.main();
await tester.pumpAndSettle();
// Логін
await tester.enterText(find.byKey(Key('email')), '[email protected]');
await tester.enterText(find.byKey(Key('password')), 'password123');
await tester.tap(find.byKey(Key('login_btn')));
await tester.pumpAndSettle(timeout: Duration(seconds: 10));
expect(find.byKey(Key('home_screen')), findsOneWidget);
// Додавання в кошик
await tester.tap(find.byKey(Key('product_card_1')));
await tester.pumpAndSettle();
await tester.tap(find.byKey(Key('add_to_cart_btn')));
await tester.pumpAndSettle();
expect(find.text('1'), findsOneWidget); // badge на іконці кошика
});
}
pumpAndSettle(timeout: Duration(seconds: 10)) — таймаут необхідний. Без нього на повільному емуляторі тест падатиме раніше, ніж анімація навігації завершиться.
Паралельне виконання
Один тест-файл — одна сесія пристрою. Для паралельного запуску створюйте кілька файлів та запускайте їх через матрицю у CI. На GitHub Actions:
strategy:
matrix:
test-file: [auth_test.dart, checkout_test.dart, profile_test.dart]
steps:
- run: flutter test integration_test/${{ matrix.test-file }}
Кожен job отримує свій емулятор. AVD Manager через reactivecircus/android-emulator-runner@v2 запускає їх паралельно.
Робота з реальними мережевими запитами
Основний вибір: тестувати проти реального бекенду або мокувати мережу.
Реальний бекенд — потрібне тестове середовище (staging). Дані повинні бути передбачувані: фіксовані тестові аккаунти, детерміновані відповіді. Мережеві помилки роблять тести нестійкими.
Мок-сервер — mockito/mocktail на рівні репозиторію, або локальний HTTP-сервер через пакет shelf. Другий варіант ближче до реальності: додаток робить справжній HTTP-запит, але на localhost:8080 замість api.production.com. Перемикання через змінну окруження або --dart-define=API_BASE_URL=http://localhost:8080.
Нестійкість інтеграційних тестів
Flaky-тести в integration_test — поширена проблема. Основні причини:
Анімації. pumpAndSettle() чекає їх завершення, але якщо у додатку є нескінченна анімація (індикатор завантаження, lottie-анімація у фоні), pumpAndSettle() зависне. Рішення: tester.pump(Duration(milliseconds: 500)) з явним чеканням конкретного віджета через waitFor.
Клавіатура. Після enterText() системна клавіатура може перекривати кнопку. Приховуйте її: await tester.testTextInput.receiveAction(TextInputAction.done) або FocusManager.instance.primaryFocus?.unfocus() перед tap().
Таймаут тесту. За замовчуванням інтеграційний тест завершується за 10 хвилин. Для довгих флоу збільшуйте: @Timeout(Duration(minutes: 5)) над testWidgets.
Строки
3–5 днів для написання інтеграційних тестів до існуючого додатку. Складний флоу з авторизацією, платежами та глибокою навігацією — ближче до 5 днів. Прості лінійні сценарії — 3 дні. Вартість розраховується після аудиту архітектури додатку.







