В чем разница между widget-тестом и unit-тестом во Flutter?

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

Ответ

Unit-тесты проверяют изолированную бизнес-логику — функции, классы, алгоритмы — без зависимостей от Flutter фреймворка. Они быстрые и используют пакет test.

// Тестируемый класс (логика)
class Calculator {
  int add(int a, int b) => a + b;
  double divide(int a, int b) {
    if (b == 0) throw ArgumentError('Cannot divide by zero');
    return a / b;
  }
}

// Unit-тест
import 'package:test/test.dart';

void main() {
  test('Calculator.add returns sum of two numbers', () {
    final calc = Calculator();
    expect(calc.add(2, 3), equals(5));
  });

  test('Calculator.divide throws error when dividing by zero', () {
    final calc = Calculator();
    expect(() => calc.divide(5, 0), throwsArgumentError);
  });
}

Widget-тесты (компонентные тесты) проверяют виджеты Flutter в изолированной среде. Они используют flutter_test, могут имитировать пользовательские взаимодействия (тап, ввод текста) и проверять построенное дерево виджетов.

// Widget-тест
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/widgets/counter_button.dart';

void main() {
  testWidgets('CounterButton increments counter on tap', (WidgetTester tester) async {
    int counter = 0;

    // Строим виджет
    await tester.pumpWidget(
      MaterialApp(
        home: CounterButton(
          count: counter,
          onPressed: () => counter++,
        ),
      ),
    );

    // Проверяем начальное состояние
    expect(find.text('Count: 0'), findsOneWidget);

    // Имитируем тап по кнопке
    await tester.tap(find.byType(ElevatedButton));
    await tester.pump(); // Перестраиваем виджет

    // Проверяем обновленное состояние (виджет перестроился с новым значением)
    expect(find.text('Count: 1'), findsOneWidget);
  });
}
Сравнение: Критерий Unit-тест Widget-тест
Скорость Быстрый (миллисекунды) Медленнее (запускает Flutter engine)
Зависимости Только Dart, без Flutter Требует Flutter фреймворк
Тестирует Логику, алгоритмы, модели UI, взаимодействие, построение виджетов
Инструмент Пакет test Пакет flutter_test, WidgetTester
Использование Тестирование ViewModel, репозиториев, утилит Тестирование виджетов, экранов, навигации