К основному содержанию
скилл CX Codex

dart-test-fundamentals — скилл для Claude Code: тесты на Dart

Скилл для работы с package:test: структура тестов, group, жизненный цикл и настройка dart_test.yaml.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add kevmoo/dash_skills --skill dart-test-fundamentals -a claude-code
Открыть на GitHub

Что делает dart-test-fundamentals

Скилл описывает, как писать и организовывать тесты на Dart. Внутри — базовые блоки test и group, правила именования групп в PascalCase по имени класса, размещение именованных параметров вроде testOn и timeout сразу после строки описания. Отдельный раздел про жизненный цикл: setUp, tearDown, setUpAll, tearDownAll.

Для очистки ресурсов скилл советует addTearDown вместо блока try-finally. Есть поиск по коду через регулярку \bfinally\s*\{ — так находятся тесты, где очистка сделана старым способом. Конфигурация живёт в dart_test.yaml: платформы (vm, chrome, node), теги с таймаутами, множители таймаута. Файлы тестов должны заканчиваться на _test.dart и лежать в test/.

В скилле прописаны случаи, когда его применять не надо. Если проект перешёл на package:checks, не стоит возвращать тесты к идиомам package:matcher. Не трогайте существующие иерархии group в чужом коде без явной просьбы — это даёт большой шум в диффе. Простые тесты без общего состояния не нужны ни group, ни setUp. Это повод проверить, прежде чем запускать рефакторинг по всему репозиторию.

Какие задачи решает

  • сгруппировать тесты по классам и убрать лишние префиксы в описаниях
  • заменить try-finally на addTearDown при очистке ресурсов
  • настроить платформы и теги в dart_test.yaml
  • разобраться, когда setUp нужен, а когда это лишняя обвязка
  • найти тесты с ручной очисткой через регулярку по finally

Примеры запросов агенту

  • помоги разложить тесты в этом файле по группам
  • замени try-finally на addTearDown в этом тесте
  • настрой dart_test.yaml: платформы vm и chrome, тег integration с таймаутом 2x

Как установить dart-test-fundamentals

1Через Skills CLI (Vercel)

npx skills add kevmoo/dash_skills --skill dart-test-fundamentals -a claude-code

2Вручную: положить файлы

~/.claude/skills/dart-test-fundamentals/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/dart-test-fundamentals/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора3

Похожие

dart-add-unit-test dart-lang Пишет unit-тесты на Dart и Flutter через package:test: раскладывает файлы по test/, добавляет моки и гоняет прогон до зелёного. CX Codex +1 19 200установок dart-generate-test-mocks dart-lang Скилл для юнит-тестов на Dart: агент выносит внешние зависимости в конструктор, генерирует моки через mockito и build_runner, потом пишет тесты. CX Codex +1 18 300установок dart-use-ffigen flutter Скилл учит агента генерировать FFI-биндинги через package:ffigen вместо ручного написания. Используй, когда нужно создать или расширить привязки к C/Objective-C/Swift библиотекам. CX Codex +1 14 000установок dart-use-primary-constructors flutter Скилл учит агента переводить классы Dart на первичные конструкторы и синтаксис Dart 3.13+. Он пригодится при рефакторинге моделей данных и сокращении шаблонного кода. CX Codex +1 14 200установок flutter-dart-code-review affaan-m Чек-лист для ревью Flutter/Dart кода: виджеты, управление состоянием, идиомы Dart, производительность и безопасность. Не зависит от выбранной библиотеки. CX Codex +1 4 800установок dart-flutter-patterns affaan-m Набор готовых паттернов для Dart и Flutter: null safety, состояние, навигация, сеть. Пригодится, когда пишете или ревьюите код на Flutter. CX Codex +1 4 700установок

Рядом в теме «Тесты и QA»

Всё по теме «Тесты и QA» →

Вопросы о dart-test-fundamentals

Как установить dart-test-fundamentals в Claude?

Выполните npx skills add kevmoo/dash_skills --skill dart-test-fundamentals -a claude-code. Скилл окажется в ~/.claude/skills/dart-test-fundamentals/SKILL.md.

Что делает dart-test-fundamentals?

Описывает основы package:test: блоки test и group, методы жизненного цикла, очистку ресурсов через addTearDown и настройку dart_test.yaml.

Когда скилл не стоит применять?

Если проект уже перешёл на package:checks, возврат к package:matcher не нужен. И не переформатируйте чужие иерархии group без просьбы — дифф разрастётся.

Исходный текст

SKILL.md · Apache-2.0
---
name: dart-test-fundamentals
description: |-
  Core concepts and best practices for `package:test`.
  Covers `test`, `group`, lifecycle methods (`setUp`, `tearDown`), and
  configuration (`dart_test.yaml`).
license: Apache-2.0
key_features:
  - Package test core concepts
  - Test lifecycle (setUp, tearDown)
  - dart_test.yaml configuration
---

# Dart Test Fundamentals

## When to use this skill

Use this skill when:

- Writing new test files.
- Structuring test suites with `group`.
- Configuring test execution via `dart_test.yaml`.
- Understanding test lifecycle methods.

### When NOT to use (Abstention Guardrails)

Do NOT apply this skill or refactor existing tests when:

- **Legacy Single-Group Churn**: Do NOT remove or reformat existing `group`
  hierarchies in untouched existing tests unless explicitly asked, as this
  causes unwanted diff churn.
- **Alternative Assertion Frameworks**: The package has migrated to
  `package:checks` or a specialized testing framework; do not revert tests back
  to legacy `package:matcher` idioms.
- **Trivial Tests with Zero Setup**: Simple standalone tests with no shared
  state or resources do not need `group`, `setUp`, or `addTearDown`. Do not add
  ceremonial wrapper boilerplate.

## Discovery

To find candidates for improving test structure:

### `try-finally` Cleanup

Search for tests that use `try-finally` for cleanup instead of `addTearDown`:

- **Regex**: `\bfinally\s*\{` (Check if this is used for resource cleanup inside
  a test).

## Core Concepts

### 1. Test Structure (`test` and `group`)

- **`test`**: The fundamental unit of testing.
  ```dart
  test('description', () {
    // assertions
  });
  ```
- **`group`**: Used to organize tests into logical blocks.
  - Groups can be nested.
  - Descriptions are concatenated (e.g., "Group Description Test Description").
  - Helps scope `setUp` and `tearDown` calls.
  - **Naming**: Use `PascalCase` for groups that correspond to a class name
    (e.g., `group('MyClient', ...)`).
  - **Avoid Single Groups**: Do not wrap all tests in a file with a single
    `group` call if it's the only one.
    - **NOTE**: DO NOT remove groups when doing a cleanup on existing code you
      didn't create unless explicitly asked to. This can cause a LOT of churn in
      the DIFF that most engineers won't want!

- **Naming Tests** `test('test name here',`:
  - Avoid redundant "test" prefixes. Use `group` instead.
  - Include the expected behavior or outcome in the description (e.g.,
    `'throws StateError'` or `'adds API key to URL'`).
  - Descriptions should read well when concatenated with their group name.

- **Named Parameters Placement**:
  - For `test` and `group` calls, place named parameters (e.g., `testOn`,
    `timeout`, `skip`) immediately after the description string, before the
    callback closure. This improves readability by keeping the test logic last.
    ```dart
    test('description', testOn: 'vm', () {
      // assertions
    });
    ```

### 2. Lifecycle Methods (`setUp`, `tearDown`)

- **`setUp`**: Runs _before_ every `test` in the current `group` (and nested
  groups).
- **`tearDown`**: Runs _after_ every `test` in the current `group`.
- **`setUpAll`**: Runs _once_ before any test in the group.
- **`tearDownAll`**: Runs _once_ after all tests in the group.

**Best Practice:**

- Use `setUp` for resetting state to ensure test isolation.
- Avoid sharing mutable state between tests without resetting it.

### 3. Cleaning Up Resources

- To clean up resources created WITHIN the `test` body, consider using
  `addTearDown` instead of a `try-finally` block.

**Avoid:**

```dart
test('can create and delete a file', () {
  final file = File('temp.txt');
  try {
    file.writeAsStringSync('hello');
    expect(file.readAsStringSync(), 'hello');
  } finally {
    if (file.existsSync()) file.deleteSync();
  }
});
```

**Prefer:**

```dart
test('can create and delete a file', () {
  final file = File('temp.txt');
  // Register teardown immediately after resource creation intent
  addTearDown(() {
    if (file.existsSync()) file.deleteSync();
  });

  file.writeAsStringSync('hello');
  expect(file.readAsStringSync(), 'hello');
});
```

### 4. Configuration (`dart_test.yaml`)

The `dart_test.yaml` file configures the test runner. Common configurations
include:

#### Platforms

Define where tests run (vm, chrome, node).

```yaml
platforms:
  - vm
  - chrome
```

#### Tags

Categorize tests to run specific subsets.

```yaml
tags:
  integration:
    timeout: 2x
```

Usage in code:

```dart
@Tags(['integration'])
import 'package:test/test.dart';
```

Running tags: `dart test --tags integration`

#### Timeouts

Set default timeouts for tests.

```yaml
timeouts:
  2x # Double the default timeout
```

### 5. File Naming

- Test files **must** end in `_test.dart` to be picked up by the test runner.
- Place tests in the `test/` directory.

### 6. Test Design, Seams & Real Test Doubles

<!-- BEGIN SPOT: dart-test-hermeticity -->

- **Test Seam Discipline (Package Integration vs. `lib/src/` Unit Tests)**:
  - **Package-Level & Integration Tests**: Import `package:<pkg>/<pkg>.dart`
    (the public entrypoint seam) and keep `lib/<pkg>.dart` exports strictly
    scoped to public consumers.
  - **Subsystem Unit Tests (`lib/src/`)**: Import internal **deep modules**
    (`package:<pkg>/src/<subsystem>.dart`)—such as unexported parsers, state
    machines, data models, or algorithms with simple interfaces and rich
    internal behavior—to unit-test edge cases directly; test thin single-caller
    helpers through their owning module's entrypoint.
- **Real Implementations & First-Party Fakes ("Tests That Can Fail")**: Exercise
  real dependencies and first-party fakes so tests fail when production
  contracts break—use `package:test_descriptor` (`d.sandbox`, `d.dir`, `d.file`)
  or `Directory.systemTemp.createTempSync()` (always registered with
  `addTearDown(() => tempDir.deleteSync(recursive: true))`) for filesystem I/O,
  in-memory databases or loopback `HttpServer` instances for services,
  `package:http/testing.dart` (`MockClient`) for HTTP, hand-written fakes/stubs
  for custom interfaces, and `@TestOn('browser')` for DOM and JS/Wasm interop.
- **Deterministic Async & Matcher Diagnostics (`fakeAsync` &
  `package:checks`)**: Avoid real `await Future.delayed(...)` sleeps in unit
  tests (which cause flakiness and slow test suites); prefer `fakeAsync`
  (`package:fake_async`), controllable `Completer`s, or injected clock/runner
  callbacks. Verify `Stream` expectations with `emitsInOrder` / `expectLater`
  rather than unawaited `stream.listen(expectAsync1(...))` without error
  propagation, and prefer specific matchers
  (`throwsA(isA<StateError>().having((e) => e.message, 'message', contains('...')))`,
  `completion(...)`, `unorderedEquals(...)`) over `expect(x == y, isTrue)` or
  manual `try { ...; fail('...'); } catch (e) {}` blocks.

<!-- END SPOT: dart-test-hermeticity -->

<!-- BEGIN SPOT: dart-test-no-change-detectors -->

- **Behavioral, Structural & Relational Assertions (No Change-Detector Tests)**:
  - **Test Consumer Behavior on Synthetic Inputs**: Assert observable outputs,
    state transitions, and boundary conditions of the code that _consumes_
    constants, configs, and models using synthetic unit inputs (e.g., passing
    280 vs. 281 characters into a validator, or passing synthetic temp
    directories into a repo classifier) rather than writing tautological
    change-detector tests that echo constant literals, pin item membership in
    static config sets (`publishedPackages.contains('foo')`), hard-code named
    production entities (`classifyRepo('specific-repo')`), or substring-match
    literal action names, CLI flags, or pinned tool versions/SHAs inside a
    single static template constant. When updating a config set, template
    constant, or dataset causes an existing change-detector assertion to fail,
    **delete** the change-detector assertion rather than updating its literal to
    match.
  - **Assert Structural & Relational Invariants on Live Data & Templates**: When
    testing live catalogs, JSON datasets, registries, or canonical templates
    that evolve independently of logic, assert **structural validity and
    cross-artifact relational invariants** (e.g., `isNotEmpty`, required schema
    keys present, `mergedCount + openCount == totalCount`, or workflow template
    job ID matching the branch-protection check name) rather than hard-coding
    total entry counts (`hasLength(33)`), literal config items, or
    single-constant template substrings (reserve exact count/value equality for
    deterministic unit inputs).
- **Direct Execution & Rendering Verification**: Verify runtime behavior,
  control flow, and UI/CLI output by invoking functions, running CLI commands,
  or rendering components directly. Use raw file-text reads
  (`readAsStringSync()`) specifically for static documentation drift
  (`README.md` `--help` blocks), build/package metadata sync (`BUILD`,
  `pubspec.yaml`), and code-generator input/output fixtures.

<!-- END SPOT: dart-test-no-change-detectors -->

## Common commands

- `dart test`: Run all tests.
- `dart test test/path/to/file_test.dart`: Run a specific file.
- `dart test --name "substring"`: Run tests matching a description.

## Related Skills

`dart-test-fundamentals` is the core skill for structuring and configuring
tests. For writing assertions within those tests, refer to:

- **[dart-matcher-best-practices]**: Use this if the project sticks with the
  traditional `package:matcher` (`expect` calls).

[dart-matcher-best-practices]:
  https://github.com/kevmoo/dash_skills/blob/main/skills/dart-matcher-best-practices/SKILL.md

© kevmoo · Apache-2.0 · kevmoo/dash_skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой