dart-test-fundamentals — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited dart-test-fundamentals (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill when:
group.dart_test.yaml.Do NOT apply this skill or refactor existing tests when:
grouphierarchies in untouched existing tests unless explicitly asked, as this causes unwanted diff churn.
package:checks or a specialized testing framework; do not revert tests back to legacy package:matcher idioms.
state or resources do not need group, setUp, or addTearDown. Do not add ceremonial wrapper boilerplate.
To find candidates for improving test structure:
try-finally CleanupSearch for tests that use try-finally for cleanup instead of addTearDown:
\bfinally\s*\{ (Check if this is used for resource cleanup insidea test).
test and group) test('description', () {
// assertions
});setUp and tearDown calls.PascalCase for groups that correspond to a class name(e.g., group('MyClient', ...)).
group call if it's the only one.
didn't create unless explicitly asked to. This can cause a LOT of churn in the DIFF that most engineers won't want!
test('test name here',:group instead.'throws StateError' or 'adds API key to URL').
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
});setUp, tearDown)test in the current group (and nestedgroups).
test in the current group.Best Practice:
setUp for resetting state to ensure test isolation.test body, consider usingaddTearDown 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');
});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: 2xUsage 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_test.dart to be picked up by the test runner.test/ directory.<!-- BEGIN SPOT: dart-test-hermeticity -->
package:<pkg>/<pkg>.dart(the public entrypoint seam) and keep lib/<pkg>.dart exports strictly scoped to public consumers.
(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 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.
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 Completers, 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 -->
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.
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).
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 -->
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.dart-test-fundamentals is the core skill for structuring and configuring tests. For writing assertions within those tests, refer to:
traditional package:matcher (expect calls).
[dart-matcher-best-practices]: https://github.com/kevmoo/dash_skills/blob/main/skills/dart-matcher-best-practices/SKILL.md
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.