Skip to content
Development
Skill

/dart-test-fundamentals

Core concepts and best practices for `package:test`. Covers `test`, `group`, lifecycle methods (`setUp`, `tearDown`), and configuration (`dart_test.yaml`).

BOOST
From plugin
dash-skills
14712 skills
Install
$ npx -y skills add kevmoo/dash_skills --skill dart-test-fundamentals --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/dart-test-fundamentals

Context preview

The summary Claude sees to decide when to auto-load this skill.

Core concepts and best practices for `package:test`. Covers `test`, `group`, lifecycle methods (`setUp`, `tearDown`), and configuration (`dart_test.yaml`).

SKILL.md

dart-test-fundamentals.SKILL.md
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.
  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.

    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:**

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:**

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).

platforms:
  - vm
  - chrome

Tags

Categorize tests to run specific subsets.

tags:
  integration:
    timeout: 2x

Usage in code:

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

Running tags: `dart test --tags integration`

Timeouts

Set default timeouts for tests.

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/

Read more
Ships withdash-skills

Agent Skills for Dart and Flutter ecosytem

Get the whole plugin

Other skills on dash-skills.