测试与调试组件
测试与调试组件用于确保应用质量和性能。
提示:良好的测试实践可以提高代码质量和维护性。
Widget 测试结果
2
总测试数
2
通过
0
失败
MyWidget 显示正确的文本
12ms
点击按钮后文本改变
8ms
Widget Tests
Widget Tests 用于测试 UI 组件的行为和外观。
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('MyWidget 显示正确的文本', (WidgetTester tester) async {
// 构建 Widget
await tester.pumpWidget(MyWidget());
// 验证文本
expect(find.text('Hello'), findsOneWidget);
});
testWidgets('点击按钮后文本改变', (WidgetTester tester) async {
await tester.pumpWidget(MyWidget());
// 查找按钮并点击
await tester.tap(find.byType(ElevatedButton));
await tester.pump();
// 验证文本已改变
expect(find.text('Clicked'), findsOneWidget);
});
}
Unit 测试结果
✓ Calculator (4 tests)
加法 - 2 + 3 = 5
减法 - 5 - 3 = 2
乘法 - 3 × 4 = 12
除法 - 10 ÷ 2 = 5
All tests passed in 24ms
Unit Tests
Unit Tests 用于测试单个函数或类的逻辑。
import 'package:flutter_test/flutter_test.dart';
void main() {
group('Calculator', () {
test('加法', () {
expect(add(2, 3), equals(5));
});
test('减法', () {
expect(subtract(5, 3), equals(2));
});
test('乘法', () {
expect(multiply(3, 4), equals(12));
});
test('除法', () {
expect(divide(10, 2), equals(5));
});
});
}
Integration Tests
Integration Tests 用于测试完整的应用流程。
import 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
void main() {
group('Counter App', () {
late FlutterDriver driver;
setUpAll(() async {
driver = await FlutterDriver.connect();
});
tearDownAll(() async {
await driver.close();
});
test('计数器递增', () async {
// 查找按钮
final counterTextFinder = find.byValueKey('counter');
final buttonFinder = find.byValueKey('increment');
// 验证初始值
expect(await driver.getText(counterTextFinder), "0");
// 点击按钮
await driver.tap(buttonFinder);
// 验证新值
expect(await driver.getText(counterTextFinder), "1");
});
});
}
Golden 测试对比
Golden 文件
goldens/my_widget.png
实际渲染
Widget 渲染结果
✓ 匹配成功
像素差异: 0%
尺寸: 200x100
Golden Tests
Golden Tests 用于验证 Widget 的视觉效果。
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('MyWidget 视觉测试', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: MyWidget(),
),
);
await expectLater(
find.byType(MyWidget),
matchesGoldenFile('goldens/my_widget.png'),
);
});
}
Mockito
Mockito 用于创建模拟对象进行测试。
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
class MockService extends Mock implements Service {}
void main() {
group('UserService', () {
late MockService mockService;
late UserService userService;
setUp(() {
mockService = MockService();
userService = UserService(mockService);
});
test('获取用户数据', () async {
// 设置模拟返回值
when(mockService.fetchUser('123'))
.thenAnswer((_) async => User(id: '123', name: 'John'));
// 执行测试
final user = await userService.getUser('123');
// 验证结果
expect(user.name, equals('John'));
verify(mockService.fetchUser('123')).called(1);
});
});
}
测试最佳实践:
- 为每个功能编写单元测试
- 为关键 UI 编写 Widget 测试
- 为主要流程编写集成测试
- 使用模拟对象隔离依赖
- 保持测试代码简洁和可维护
测试金字塔
E2E 测试
少量
少量
Widget 测试
适量
适量
Unit 测试
大量
大量
🟢 Unit 测试: 70% - 快速、独立、覆盖逻辑
🔵 Widget 测试: 20% - 测试 UI 组件
🟠 E2E 测试: 10% - 测试完整流程
运行测试命令:
- flutter test: 运行所有测试
- flutter test test/widget_test.dart: 运行特定测试
- flutter drive --target=test_driver/app.dart: 运行集成测试
- flutter test --update-goldens: 更新 golden 文件