Migrating Dart Tests to Package Checks
Contents
Dependency Management
Manage dependencies using the Dart Tooling MCP Server pub tool or standard CLI commands.
- Add
package:checksas adev_dependencyusingdart pub add dev:checks. - Remove
package:matcherif it is explicitly listed in thepubspec.yaml(note: it is often transitively included bypackage:test, which is fine). - Import
package:checks/checks.dartin all test files undergoing migration.
Syntax Migration Guidelines
Transition test assertions from the package:matcher syntax to the literate API provided by package:checks.
- Basic Equality: Replace
expect(actual, equals(expected))orexpect(actual, expected)withcheck(actual).equals(expected). - Type Checking: Replace
expect(actual, isA<Type>())withcheck(actual).isA<Type>(). - Property Extraction: Replace
expect(actual.property, expected)withcheck(actual).has((a) => a.property, 'property name').equals(expected). - Cascades for Multiple Checks: Use Dart's cascade operator (
..) to chain multiple expectations on a single subject. - Asynchronous Expectations:
- If checking a Future, await the check call: await check(someFuture).completes((r) => r.equals(expected));. - If checking a Stream, wrap it in a StreamQueue for multiple checks, or use .withQueue for single/broadcast checks.
Utilizing Dart MCP Tools
Leverage the Dart MCP Server tools to automate and validate the migration process.
- Use
pubto rundart pub getordart pub add. - Use
analyze_filesto run static analysis on the project or specific paths. - Use
run_teststo execute Dart or Flutter tests with an agent-centric UX. ALWAYS use this instead of shell commands likedart test. - Use
dart_fixto apply automated fixes if applicable.
Migration Workflow
Copy and use the following checklist to track progress when migrating a test suite:
- Task Progress
- Add package:checks as a dev dependency. - Identify all test files using package:matcher (expect calls). - Import package:checks/checks.dart in target test files. - Rewrite all expect(...) statements to check(...) statements. - Run static analyzer (analyze_files). - Run tests (run_tests).
Feedback Loop: Static Analysis
- Run the
analyze_filestool on the modified test directories. - Review any static analysis warnings or errors (e.g., missing imports, incorrect generic types on
isA, unawaited futures). - Fix the warnings.
- Repeat until the analyzer returns zero issues.
Feedback Loop: Test Validation
- Run the
run_teststool. - If tests fail, review the failure output.
package:checksprovides detailed context (e.g.,Which: has length of <2>). - Adjust the
check()expectations or the underlying code to resolve the failure. - Repeat until all tests pass.
Examples
Basic Assertions
Input (matcher):
expect(someList.length, 1);
expect(someString, startsWith('a'));
expect(someObject, isA<Map>());Output (checks):
check(someList).length.equals(1);
check(someString).startsWith('a');
check(someObject).isA<Map>();Composed Expectations
Input (matcher):
expect('foo,bar,baz', allOf([
contains('foo'),
isNot(startsWith('bar')),
endsWith('baz')
]));Output (checks):
check('foo,bar,baz')
..contains('foo')
..not((s) => s.startsWith('bar'))
..endsWith('baz');Asynchronous Futures
Input (matcher):
expect(Future.value(10), completion(equals(10)));
expect(Future.error('oh no'), throwsA(equals('oh no')));Output (checks):
await check(Future.value(10)).completes((it) => it.equals(10));
await check(Future.error('oh no')).throws<String>().equals('oh no');Asynchronous Streams
Input (matcher):
var stdout = StreamQueue(Stream.fromIterable(['Ready', 'Go']));
await expectLater(stdout, emitsThrough('Ready'));Output (checks):
var stdout = StreamQueue(Stream.fromIterable(['Ready', 'Go']));
await check(stdout).emitsThrough((it) => it.equals('Ready'));