测试
Unit/Widget/Integration。
测试
这一课你将能做到
- 写单元测试(Unit Test)验证纯 Dart 业务逻辑
- 写 Widget 测试验证 UI 组件的渲染和交互
- 用
mockito或mocktail做依赖 Mock,写集成测试(Integration Test)跑完整流程
为什么要学
Flutter 的测试金字塔:Unit 测试最多最快,Widget 测试居中,Integration 测试最少最慢但最接近真实。不写测试,改代码就是开盲盒。
人话:Unit 测试是「检查零件」,Widget 测试是「检查组装」,Integration 测试是「上路试驾」。三层配合,bug 无处藏身。
先建立图像
/\
/ \ Integration Test(少、慢、全链路)
/____\
/ \ Widget Test(中、较快、单组件)
/________\
/ \ Unit Test(多、快、纯逻辑)
/____________\
跟着做
步骤 1:添加测试依赖
pubspec.yaml:
dev_dependencies:
flutter_test:
sdk: flutter
mocktail: ^1.0.0
integration_test:
sdk: flutter
步骤 2:单元测试
// lib/calculator.dart
class Calculator {
int add(int a, int b) => a + b;
int divide(int a, int b) {
if (b == 0) throw ArgumentError('除数不能为 0');
return a ~/ b;
}
}
// test/calculator_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:myapp/calculator.dart';
void main() {
group('Calculator', () {
final calc = Calculator();
test('add 正常', () {
expect(calc.add(2, 3), 5);
});
test('divide 正常', () {
expect(calc.divide(10, 2), 5);
});
test('divide 除 0 抛异常', () {
expect(() => calc.divide(1, 0), throwsArgumentError);
});
});
}
运行:
flutter test
步骤 3:Widget 测试
// lib/counter_page.dart
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(child: Text('$_count')),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _count++),
child: const Icon(Icons.add),
),
);
}
}
// test/counter_page_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:myapp/counter_page.dart';
void main() {
testWidgets('点击按钮计数器增加', (tester) async {
await tester.pumpWidget(const MaterialApp(home: CounterPage()));
expect(find.text('0'), findsOneWidget);
await tester.tap(find.byIcon(Icons.add));
await tester.pump(); // 触发 rebuild
expect(find.text('1'), findsOneWidget);
});
}