mcpField
F
flutter-testing

flutter-testing

github.com/dhruvanbhalara测试与质量30274 次安装9 周前更新
代码仓库

关于 flutter-testing

面向 Flutter 开发者的测试策略技能,规定覆盖率、组织方式、独立性和命名的实践,并介绍适用于单元、组件和集成测试的黄金图变体、状态矩阵及交互契约模式。

主要功能

  1. 01测试金字塔与覆盖率指导
  2. 02测试文件镜像式组织
  3. 03独立测试规范
  4. 04黄金图变体测试模式
  5. 05状态矩阵与交互契约模式

适用场景

  1. 01测试设计系统组件的视觉变体
  2. 02检查有状态组件的全部状态
  3. 03验证可复用组件的交互规则
  4. 04运行单元、组件或集成测试

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dhruvanbhalara/skills --skill flutter-testing

安装后在 Claude Code 中输入/flutter-testing确认已加载。

详细介绍

测试策略

  • 测试金字塔:更多单元测试和组件测试,更少集成测试。单元测试速度最快、成本最低。
  • 镜像测试规则:逻辑和组件覆盖率达到 100%。所有代码都必须有测试。
  • 镜像组织结构:测试文件必须严格镜像 lib/ 目录结构,并以 _test.dart 结尾。
  • 覆盖率目标:domain 和 bloc 层的逻辑覆盖率目标为 100%。
  • 测试独立性:每个测试必须相互独立。测试之间不得共享可变状态。

测试类型概览

类型范围速度技能
单元测试单个函数/类快dart-testing
组件测试单个 UI 组件中flutter-add-widget-test
集成测试完整应用 / 用户流程慢flutter-add-integration-test

基于模式的测试

以下三种模式可以减少重复的测试设置、覆盖所有视觉状态,并确保组件行为一致。它们是约定,而非软件包。

Golden 变体测试

当组件有多种视觉状态(主要、禁用、悬停、错误)时,应在一个结构化的 group() 中使用 Map<String, Widget Function()> 测试所有变体:

  • 定义一个 variants 映射,其中键为状态名称,值为组件构建器。
  • 每个变体都必须单独渲染(每个变体调用一次全新的 pumpWidget)。
  • 使用确定性的 Golden 文件命名:goldens/<component>.<variant>.png。
  • 通过 tester.view.physicalSize 设置一致的 surfaceSize,避免像素差异测试出现不稳定结果。
  • 适用场景:设计系统组件、具有不同模式/类型的组件。
  • 不适用场景:集成测试或动画帧验证。

状态矩阵测试

每个有状态组件都必须针对所有可能的 UI 状态进行测试。使用状态矩阵将设置与验证分开:

  • 定义一个 states 映射,包含组件可以呈现的每种状态(loading、error、data、empty)。
  • 编写一个 verify(stateName) 回调,使用 switch 表达式断言每种状态下的正确渲染结果。
  • 此模式可以避免只测试“正常路径”这一常见错误。
  • 适用场景:具有复杂状态机的组件(例如由 BLoC 驱动的屏幕)。
  • 不适用场景:如果不同状态的验证逻辑差异很大,应编写单独的测试。

交互契约测试

可复用组件有隐含的行为规则。应将这些规则定义为明确且可复用的契约:

  • 在 test/utils/ 中为常见契约创建辅助函数:
    • verifyTappable(tester, finder, mockCallback):点击会准确触发一次回调。
    • verifyDisabledNotTappable(tester, finder, mockCallback):禁用时点击不会触发回调。
    • verifyValidatesOnBlur(tester, finder):焦点离开时触发验证。
  • 在所有行为相同的组件中一致地应用这些契约。
  • 适用场景:行为规则严格明确,且重构后仍必须成立的组件。
  • 不适用场景:仅某个组件独有的一次性逻辑。

测试命名与结构

  • 测试命名:使用字符串插值作为测试组名称:group('$ClassName',,而不是 group('ClassName',。这可确保一致性,并提供更好的工具支持。
  • 测试分组:使用 group() 按功能、类或状态组织测试,以便更清晰地查看报告。
  • 描述性名称:测试名称应清楚说明测试内容及原因。

常见测试错误

  • A RenderFlex overflowed...:在测试中用 Expanded 包裹组件,或限制其尺寸
  • Vertical viewport was given unbounded height:在测试中用具有固定高度的 SizedBox 包裹 ListView
  • setState called during build:将状态更改延迟到帧后回调中
  • No MediaQuery widget ancestor:始终用 MaterialApp 包裹测试组件

运行测试(快速参考)

  • flutter test:运行所有单元测试和组件测试
  • flutter test test/path/to/file_test.dart:运行指定的测试文件
  • flutter test integration_test/:运行集成测试
  • flutter test --coverage:运行测试并生成覆盖率报告
  • dart test:运行纯 Dart 单元测试

评论

支持 Markdown