skills/dart-matcher-best-practices/SKILL.md
Best practices for using `expect` and `package:matcher`. Focuses on readable assertions, proper matcher selection, and avoiding common pitfalls.
npx skillsauth add kevmoo/dash_skills dart-matcher-best-practicesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill when:
expect and package:matcher.To find candidates for improving matcher usage, search for suboptimal patterns:
Search for length checks that should use hasLength:
expect\([^,]+.length,\s*Search for checks on boolean properties that have specific matchers:
expect\([^,]+.isEmpty,\s*(true|equals\(true\))expect\([^,]+.isNotEmpty,\s*(true|equals\(true\))expect\([^,]+.contains\(.*\),\s*(true|equals\(true\))Search for manual map lookups instead of containsPair:
expect\([^,]+\[.*\],\s*hasLength, contains, isEmpty, unorderedEquals, containsPair)hasLength(n):
expect(list, hasLength(n)) over expect(list.length, n).isEmpty / isNotEmpty:
expect(list, isEmpty) over expect(list.isEmpty, true).expect(list, isNotEmpty) over expect(list.isNotEmpty, true).contains(item):
expect(list.contains(item), true).unorderedEquals(items):
expect(list, containsAll(items)).containsPair(key, value):
expect(map[key], value) or
expect(map.containsKey(key), true).isA<T> and TypeMatcher<T>)isA<T>():
expect(obj, isA<Type>()).TypeMatcher<Type>()..having().TypeMatcher<T>:
const: const isMyType = TypeMatcher<MyType>();.having() works here too, but the resulting matcher is not const.having)Use .having() on isA<T>() or other TypeMatchers to check properties.
(e) => e.message) instead of generic ones like p0 to improve readability.expect(person, isA<Person>()
.having((p) => p.name, 'name', 'Alice')
.having((p) => p.age, 'age', greaterThan(18)));
This provides detailed failure messages indicating exactly which property failed.
completion(matcher):
await expectLater(...) to ensure the future completes before
the test continues.await expectLater(future, completion(equals(42))).throwsA(matcher):
await expectLater(future, throwsA(isA<StateError>())).expect(() => function(), throwsA(isA<ArgumentError>())) (synchronous
function throwing is fine with expect).expectLaterUse await expectLater(...) when testing async behavior to ensure proper
sequencing.
// GOOD: Waits for future to complete before checking side effects
await expectLater(future, completion(equals(42)));
expect(sideEffectState, equals('done'));
// BAD: Side effect check might run before future completes
expect(future, completion(equals(42)));
expect(sideEffectState, equals('done')); // Race condition!
if statements or for loops for
assertions; let matchers handle it.containsPair for maps instead of checking keys manually).package:matcher to modern
package:checks.testing
Core concepts and best practices for `package:test`. Covers `test`, `group`, lifecycle methods (`setUp`, `tearDown`), and configuration (`dart_test.yaml`).
testing
Understand and improve test coverage in a Dart package. Helps agents run coverage, interpret results, and identify missed lines.
documentation
Guidelines for maintaining external Dart packages, covering versioning, publishing workflows, and pull request management. Use when updating Dart packages, preparing for a release, or managing collaborative changes in a repository.
development
Guidelines and best practices for refactoring consecutive prints, single-line string concatenations, and complex output blocks into triple-quoted multi-line string literals (''' or """) in Dart.