Ответ
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, репозиториев, утилит | Тестирование виджетов, экранов, навигации |
Ответ 18+ 🔞
А, ну так, слушай, тут про тесты в Flutter'е объясняют. В общем, смотри, есть два основных вида, и если их не различать — это пиздец, а не разработка. Сейчас разжую.
Unit-тесты — это, блядь, святое. Они проверяют голую бизнес-логику: твои функции, классы, алгоритмы. Всё это безо всякой привязки к самому Flutter'у, то есть фреймворк им нахуй не упёрся. Они быстрые, как угорелые, и используют пакет test. Просто, понятно, без лишней ебалы.
Вот смотри, как это выглядит. Берём какой-нибудь класс Calculator, который складывает и делит. Ну, обычная математика, ёпта.
// Тестируемый класс (логика)
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);
});
}
Видишь? Никаких виджетов, никакого WidgetTester'а. Чистая логика. Написал, запустил — и через полсекунды уже знаешь, работает твоя функция или она — пидарас шерстяной, который на ноль делит.
А теперь Widget-тесты (или компонентные). Вот тут уже начинается ёперный театр. Они проверяют сами виджеты, но в изолированной среде. Используют 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);
});
}
Смотри, что происходит: ты поднимаешь целый Flutter engine, чтобы проверить одну кнопку. Это уже не миллисекунды, а ощутимо дольше. Но зато ты уверен, что UI не разъёбывается при первом же клике.
Так в чём разница, спросишь ты? Да вот, смотри табличку, я для таких, как ты, собрал:
| Критерий | Unit-тест | Widget-тест |
|---|---|---|
| Скорость | Быстрый (миллисекунды) | Медленнее (запускает Flutter engine) |
| Зависимости | Только Dart, без Flutter | Требует Flutter фреймворк |
| Тестирует | Логику, алгоритмы, модели | UI, взаимодействие, построение виджетов |
| Инструмент | Пакет test |
Пакет flutter_test, WidgetTester |
| Использование | Тестирование ViewModel, репозиториев, утилит | Тестирование виджетов, экранов, навигации |
Короче, суть в чём: unit-тесты — это для твоего бэкенда в приложении, для всяких AuthService или OrderCalculator. А widget-тесты — это когда тебе надо убедиться, что твой красивый экран с анимациями не превращается в манда с ушами после обновления состояния. Если будешь всё unit-тестами покрывать — доверия ебать ноль к UI останется. Если всё widget-тестами гонять — будешь ждать сборку до второго пришествия. Сочетай, ебать копать, с умом.