prefer_test_matchers
v0.4.0 Warning Testing Rules
Flags an expect() or expectLater() call whose second argument is a plain value rather than a Matcher.
expect(x, 1) passes and fails correctly, but when it fails all it can say is Expected: <1> Actual: <2>. A matcher describes the assertion, so the failure names it.
Each of these asserts the right thing and reports it badly:
void main() { test('keeps three scores', () { final scores = [7, 8, 9];
expect(scores.length, 3); expect(scores, [7, 8, 9]); expect(scores.isEmpty, false); });}expect(scores.length, 3) failing prints Expected: <3> Actual: <2> — the
count, not the list. You then go and print the list by hand.
The same three assertions, said with matchers:
void main() { test('keeps three scores', () { final scores = [7, 8, 9];
expect(scores, hasLength(3)); expect(scores, equals([7, 8, 9])); expect(scores, isNotEmpty); });}Now the first one failing prints
Expected: an object with length of <3> Actual: [7, 8] Which: has length of <2>.
The everyday swaps
Section titled “The everyday swaps”| Instead of | Write |
|---|---|
expect(value, 'hello') |
expect(value, equals('hello')) |
expect(flag, true) |
expect(flag, isTrue) |
expect(flag, false) |
expect(flag, isFalse) |
expect(result, null) |
expect(result, isNull) |
expect(items.length, 3) |
expect(items, hasLength(3)) |
expect(items, [1, 2]) |
expect(items, equals([1, 2])) |
void main() { test('parses a greeting', () { final value = 'hello'; final result = null; final flag = true;
expect(value, equals('hello')); expect(flag, isTrue); expect(result, isNull); });}expectLater too
Section titled “expectLater too”The rule reads the second argument of both functions:
void main() { test('resolves to three scores', () async { // Don't await expectLater(loadScores(), completion([7, 8, 9]));
// Do await expectLater(loadScores(), completion(equals([7, 8, 9]))); });}
Future<List<int>> loadScores() async => [7, 8, 9];Never reported
Section titled “Never reported”A Matcher in any form satisfies the rule — including one held in a variable,
and isA<T>():
void main() { test('accepts a matcher from a variable', () { final expected = equals(42);
expect(1 + 41, expected); expect('hello', isA<String>()); });}A reason: named argument is ignored, since the rule only reads the second
positional argument.
See also: test package - Matchers
Configuration
Section titled “Configuration”This rule is in the opinionated preset, so it is on with
preset: opinionated, or by name:
rules: prefer_test_matchers: trueTo turn it off again:
rules: prefer_test_matchers: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”avoid_misused_test_matchers— Detect test matchers used with incompatible value types.prefer_expect_later— Use ‘expectLater’ instead of ‘expect’ when testing Futures.format_test_name— Hold test descriptions to a house pattern.prefer_correct_test_file_name— Name test files so the runner actually runs them.