Migrating Dart Tests to Package Checks
Contents
- Dependency Management
- Syntax Migration Guidelines
- Utilizing Dart MCP Tools
- Migration Workflow
- Examples
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,awaitthecheckcall:await check(someFuture).completes((r) => r.equals(expected));. - If checking a
Stream, wrap it in aStreamQueuefor multiple checks, or use.withQueuefor single/broadcast checks.
- If checking a
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:checksas a dev dependency. - Identify all test files using
package:matcher(expectcalls). - Import
package:checks/checks.dartin target test files. - Rewrite all
expect(...)statements tocheck(...)statements. - Run static analyzer (
analyze_files). - Run tests (
run_tests).
- Add
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'));