Есть ли опыт написания тестов?

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

Ответ

Да, я активно пишу тесты для Flutter-приложений, покрывая различные уровни: unit, widget и интеграционные тесты.

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

// Пример теста для класса Counter
import 'package:test/test.dart';

class Counter {
  int value = 0;
  void increment() => value++;
  void decrement() => value--;
}

void main() {
  group('Counter', () {
    test('value should start at 0', () {
      expect(Counter().value, 0);
    });

    test('value should be incremented', () {
      final counter = Counter();
      counter.increment();
      expect(counter.value, 1);
    });
  });
}

2. Widget-тесты (пакет flutter_test): Позволяют тестировать виджеты в изоляции, проверять их состояние и реакцию на взаимодействие.

// Пример теста для виджета
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('MyWidget displays a title and responds to tap', (WidgetTester tester) async {
    // Строим виджет
    await tester.pumpWidget(const MyWidget(title: 'T'));
    // Проверяем, что текст отобразился
    expect(find.text('T'), findsOneWidget);
    // Имитируем нажатие на кнопку
    await tester.tap(find.byType(ElevatedButton));
    await tester.pump(); // Триггерим перестроение
    // Проверяем результат
    expect(find.text('Clicked!'), findsOneWidget);
  });
}

3. Интеграционные тесты (пакет integration_test): Запускаю на реальном устройстве или эмуляторе для проверки полного сценария работы приложения.

// Пример интеграционного теста
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:my_app/main.dart' as app;

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('Full app flow', (WidgetTester tester) async {
    app.main(); // Запускаем приложение
    await tester.pumpAndSettle(); // Ждем полной отрисовки
    // Выполняем последовательность действий
    await tester.tap(find.byIcon(Icons.add));
    await tester.pumpAndSettle();
    // Проверяем итоговое состояние UI
    expect(find.text('1'), findsOneWidget);
  });
}

Дополнительно: Для мокирования зависимостей (например, http.Client или репозиториев) использую mocktail или mockito. Тестовый конвейер настраиваю через flutter test для модульных/виджет-тестов и flutter test integration_test для интеграционных.