testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTesting Strategy
测试策略
- Test Pyramid: More unit and widget tests, fewer integration tests. Unit tests are fastest and cheapest.
- Mirror Test Rule: 100% logic and widget coverage. No code without a test.
- Mirror Organization: Test files MUST strictly mirror the directory structure and end with
lib/._test.dart - Coverage Targets: Target 100% logic coverage for and
domainlayers.bloc - Test Independence: Each test MUST be independent. No shared mutable state between tests.
- 测试金字塔:多写单元测试和widget测试,少写集成测试。单元测试速度最快、成本最低。
- 镜像测试规则:实现100%的逻辑和widget覆盖率,不存在无测试的代码。
- 镜像组织结构:测试文件必须严格镜像目录结构,且以
lib/结尾。_test.dart - 覆盖率目标:层和
domain层的逻辑覆盖率目标为100%。bloc - 测试独立性:每个测试必须独立,测试之间不能共享可变状态。
Unit Testing
单元测试
- Follow the Arrange-Act-Assert (Given-When-Then) convention for clear and maintainable tests
- Use mocks for dependencies except for lightweight third-party services
- Test business logic in isolation from the UI
- For tests, ensure to create 5 to 8 tests for logical operations with real scenarios
- Mocking Protocol: Use for all dependency mocking. STRICTLY prohibit using real implementation dependencies in unit tests.
mocktail - Pure Logic: Business logic inside BLoCs or UseCases should be extracted to static pure functions for 100% unit test coverage.
- 遵循Arrange-Act-Assert(Given-When-Then)规范,保证测试清晰易维护
- 依赖项使用mock,轻量第三方服务除外
- 业务逻辑测试要与UI隔离
- 针对逻辑操作,需结合真实场景编写5到8个测试用例
- Mock规范:所有依赖项的mock都使用,严格禁止在单元测试中使用真实实现的依赖
mocktail - 纯逻辑要求:BLoC或UseCase中的业务逻辑应提取为静态纯函数,以实现100%的单元测试覆盖率
Widget Testing
Widget测试
- Write widget tests for all major UI components
- Test user interactions and state changes
- Widget Keys: Use format on interactive widgets for test access
Key('feature_action_id') - Test Localization: Use (
AppLocalizations) in widget tests — no hardcoded stringscontext.l10n
- 为所有核心UI组件编写widget测试
- 测试用户交互和状态变化
- Widget Key规范:在可交互widget上使用格式的命名,方便测试访问
Key('feature_action_id') - 本地化测试:在widget测试中使用(
AppLocalizations),禁止硬编码字符串context.l10n
Integration Testing
集成测试
- Use at the start of integration tests
IntegrationTestWidgetsFlutterBinding.ensureInitialized() - Interact with widgets via (e.g.,
Key)find.byKey(const ValueKey('increment')) - Use to wait for animations and async operations to complete
pumpAndSettle() - Run with:
flutter test integration_test/
- 集成测试开头需要调用
IntegrationTestWidgetsFlutterBinding.ensureInitialized() - 通过和widget交互(例如
Key)find.byKey(const ValueKey('increment')) - 使用等待动画和异步操作执行完成
pumpAndSettle() - 运行命令:
flutter test integration_test/
Test Naming & Structure
测试命名与结构
- Test Naming: Use string interpolation for test group names: not
group('$ClassName',. This ensures consistency and enables better tooling support.group('ClassName', - Test Grouping: Use to organize tests by feature, class, or state for clearer reporting.
group() - Descriptive Names: Test names should clearly describe what is being tested and why.
- 测试命名:测试组名称使用字符串插值:而非
group('$ClassName',,这样可以保证一致性,获得更好的工具支持group('ClassName', - 测试分组:使用按功能、类或状态组织测试,让测试报告更清晰
group() - 描述性命名:测试名称应清晰描述测试对象和测试目的
Common Test Errors
常见测试错误
- — Wrap widget in
A RenderFlex overflowed...or constrain dimensions in testExpanded - — Wrap
Vertical viewport was given unbounded heightinListViewwith fixed height in testSizedBox - — Defer state changes to post-frame callback
setState called during build
- — 测试中把widget包裹在
A RenderFlex overflowed...中,或者限制其尺寸Expanded - — 测试中把
Vertical viewport was given unbounded height包裹在固定高度的ListView中SizedBox - — 把状态变更延迟到帧后回调中执行
setState called during build
Running Tests
运行测试
- — Run all unit and widget tests
flutter test - — Run specific test file
flutter test test/path/to/file_test.dart - — Run integration tests
flutter test integration_test/ - — Run with coverage report
flutter test --coverage
- — 运行所有单元测试和widget测试
flutter test - — 运行指定的测试文件
flutter test test/path/to/file_test.dart - — 运行集成测试
flutter test integration_test/ - — 运行测试并生成覆盖率报告
flutter test --coverage