mcpField
D
dart-add-unit-test

dart-add-unit-test

github.com/dart-lang测试与质量53219.4k 次安装2 周前更新
代码仓库

关于 dart-add-unit-test

为 Dart 和 Flutter 项目提供单元测试编写与执行指南,面向开发者。内容涵盖测试文件组织、测试结构、异步测试、模拟依赖和运行命令。

主要功能

  1. 01按 lib 目录组织测试文件
  2. 02使用 group、test 和 expect
  3. 03编写异步测试及生命周期钩子
  4. 04使用 Mockito 模拟依赖
  5. 05运行单元及集成测试

适用场景

  1. 01为 Dart 包创建单元测试
  2. 02为 Flutter 应用编写测试
  3. 03验证依赖注入场景
  4. 04执行集成测试套件

安装

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

$npx skills add https://github.com/dart-lang/skills --skill dart-add-unit-test

安装后在 Claude Code 中输入/dart-add-unit-test确认已加载。

详细介绍

测试 Dart 和 Flutter 应用

目录

测试文件的组织方式

将测试文件的结构与 lib 目录保持一致,以确保结构清晰、易于预测。

  • 将所有测试代码放在包根目录下的 test 目录中。
  • 所有测试文件名均以 _test.dart 结尾(例如,应在 test/src/utils_test.dart 中测试 lib/src/utils.dart)。
  • 如果编写集成测试,请将其放在包根目录下的 integration_test 目录中。

编写测试

将 package:test 用作 Dart 应用的标准测试库。

  • 导入 package:test/test.dart(Flutter 项目则导入 package:flutter_test/flutter_test.dart)。
  • 使用 group() 函数将相关测试分组,以共享上下文。
  • 使用 test() 函数定义单个测试用例。
  • 使用 expect() 函数和匹配器(例如 equals()、isTrue、throwsA())验证结果。
  • 使用标准的 async/await 语法编写异步测试。测试运行器会自动等待 Future 完成。
  • 使用 setUp() 和 tearDown() 回调管理测试的设置和清理。
  • 如果测试依赖注入相关代码,可将 package:mockito 与 package:test 搭配使用,以生成模拟对象、配置固定场景并验证交互。

运行测试

根据项目类型和测试位置选择合适的测试运行器。

  • 如果是纯 Dart 项目,使用 dart test 命令运行测试。
  • 如果是 Flutter 项目,使用 flutter test 命令运行测试。
  • 如果运行集成测试,请明确指定目录路径,因为默认运行器会忽略该目录:dart test integration_test 或 flutter test integration_test。

测试实现工作流

实现新的测试套件时,请按以下顺序进行。复制此清单以跟踪进度。

任务进度
  • 1. 在 test/ 目录中创建测试文件,并确保其以 _test.dart 结尾。
  • 2. 导入 package:test/test.dart 和目标库。
  • 3. 定义 main() 函数。
  • 4. 使用 setUp() 初始化共享资源或模拟对象。
  • 5. 使用 group() 按功能分组编写 test() 用例。
  • 6. 使用合适的 CLI 命令运行测试套件。
  • 7. 反馈循环:运行测试 -> 查看失败的堆栈跟踪 -> 修复实现或断言 -> 重新运行直至通过。

示例

标准单元测试套件

演示如何进行分组、设置、同步测试和异步测试。

import 'package:test/test.dart';
import 'package:my_package/calculator.dart';

void main() {
  group('Calculator', () {
    late Calculator calc;

    setUp(() {
      calc = Calculator();
    });

    test('adds two numbers correctly', () {
      expect(calc.add(2, 3), equals(5));
    });

    test('handles asynchronous operations', () async {
      final result = await calc.fetchRemoteValue();
      expect(result, isNotNull);
      expect(result, greaterThan(0));
    });
  });
}
使用 Mockito 进行模拟

演示如何配置模拟对象以测试依赖注入。

import 'package:test/test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'package:my_package/api_client.dart';
import 'package:my_package/data_service.dart';

// Generate the mock using build_runner: dart run build_runner build
@GenerateNiceMocks([MockSpec<ApiClient>()])
import 'data_service_test.mocks.dart';

void main() {
  group('DataService', () {
    late MockApiClient mockApiClient;
    late DataService dataService;

    setUp(() {
      mockApiClient = MockApiClient();
      dataService = DataService(apiClient: mockApiClient);
    });

    test('returns parsed data on successful API call', () async {
      // Configure the mock
      when(mockApiClient.get('/data')).thenAnswer((_) async => '{"id": 1}');

      // Execute the system under test
      final result = await dataService.fetchData();

      // Verify outcomes and interactions
      expect(result.id, equals(1));
      verify(mockApiClient.get('/data')).called(1);
    });
  });
}

评论

支持 Markdown