|
35 | 35 |
|
36 | 36 | ## Writing Tests |
37 | 37 |
|
38 | | -Tests are specified using the top-level [`test()`] function, and test assertions |
39 | | -are made using [`expect()`]: |
| 38 | +Tests are specified using the top-level [`test()`] function. |
| 39 | +Test asserts can be made using [`expect` from `package:matcher`][expect] |
40 | 40 |
|
41 | 41 | [`test()`]: https://pub.dev/documentation/test_core/latest/test_core.scaffolding/test.html |
42 | 42 |
|
43 | | -[`expect()`]: https://pub.dev/documentation/test_api/latest/expect/expect.html |
| 43 | +[expect]: https://pub.dev/documentation/matcher/latest/expect/expect.html |
44 | 44 |
|
45 | 45 | ```dart |
46 | 46 | import 'package:test/test.dart'; |
@@ -91,42 +91,6 @@ void main() { |
91 | 91 | } |
92 | 92 | ``` |
93 | 93 |
|
94 | | -Any matchers from the [`matcher`] package can be used with `expect()` to do |
95 | | -complex validations: |
96 | | - |
97 | | -[`matcher`]: https://pub.dev/documentation/matcher/latest/matcher/matcher-library.html |
98 | | - |
99 | | -```dart |
100 | | -import 'package:test/test.dart'; |
101 | | -
|
102 | | -void main() { |
103 | | - test('.split() splits the string on the delimiter', () { |
104 | | - expect('foo,bar,baz', allOf([ |
105 | | - contains('foo'), |
106 | | - isNot(startsWith('bar')), |
107 | | - endsWith('baz') |
108 | | - ])); |
109 | | - }); |
110 | | -} |
111 | | -``` |
112 | | - |
113 | | -You can also test exceptions with the [`throwsA()`] function or a matcher |
114 | | -such as [`throwsFormatException`]: |
115 | | - |
116 | | -[`throwsA()`]: https://pub.dev/documentation/test_api/latest/expect/throwsA.html |
117 | | - |
118 | | -[`throwsFormatException`]: https://pub.dev/documentation/test_api/latest/expect/throwsFormatException-constant.html |
119 | | - |
120 | | -```dart |
121 | | -import 'package:test/test.dart'; |
122 | | -
|
123 | | -void main() { |
124 | | - test('.parse() fails on invalid input', () { |
125 | | - expect(() => int.parse('X'), throwsFormatException); |
126 | | - }); |
127 | | -} |
128 | | -``` |
129 | | - |
130 | 94 | You can use the [`setUp()`] and [`tearDown()`] functions to share code between |
131 | 95 | tests. The `setUp()` callback will run before every test in a group or test |
132 | 96 | suite, and `tearDown()` will run after. `tearDown()` will run even if a test |
@@ -478,189 +442,6 @@ Avoid uncaught async errors by ensuring that all futures have an error handler |
478 | 442 |
|
479 | 443 | [early-handler]:https://dart.dev/guides/libraries/futures-error-handling#potential-problem-failing-to-register-error-handlers-early |
480 | 444 |
|
481 | | -### Future Matchers |
482 | | - |
483 | | -There are a number of useful functions and matchers for more advanced |
484 | | -asynchrony. The [`completion()`] matcher can be used to test `Futures`; it |
485 | | -ensures that the test doesn't finish until the `Future` completes, and runs a |
486 | | -matcher against that `Future`'s value. |
487 | | - |
488 | | -[`completion()`]: https://pub.dev/documentation/test_api/latest/expect/completion.html |
489 | | - |
490 | | -```dart |
491 | | -import 'dart:async'; |
492 | | -
|
493 | | -import 'package:test/test.dart'; |
494 | | -
|
495 | | -void main() { |
496 | | - test('Future.value() returns the value', () { |
497 | | - expect(Future.value(10), completion(equals(10))); |
498 | | - }); |
499 | | -} |
500 | | -``` |
501 | | - |
502 | | -The [`throwsA()`] matcher and the various [`throwsExceptionType`] matchers work |
503 | | -with both synchronous callbacks and asynchronous `Future`s. They ensure that a |
504 | | -particular type of exception is thrown: |
505 | | - |
506 | | -[`throwsExceptionType`]: https://pub.dev/documentation/test_api/latest/expect/throwsException-constant.html |
507 | | - |
508 | | -```dart |
509 | | -import 'dart:async'; |
510 | | -
|
511 | | -import 'package:test/test.dart'; |
512 | | -
|
513 | | -void main() { |
514 | | - test('Future.error() throws the error', () { |
515 | | - expect(Future.error('oh no'), throwsA(equals('oh no'))); |
516 | | - expect(Future.error(StateError('bad state')), throwsStateError); |
517 | | - }); |
518 | | -} |
519 | | -``` |
520 | | - |
521 | | -The [`expectAsync()`] function wraps another function and has two jobs. First, |
522 | | -it asserts that the wrapped function is called a certain number of times, and |
523 | | -will cause the test to fail if it's called too often; second, it keeps the test |
524 | | -from finishing until the function is called the requisite number of times. |
525 | | - |
526 | | -```dart |
527 | | -import 'dart:async'; |
528 | | -
|
529 | | -import 'package:test/test.dart'; |
530 | | -
|
531 | | -void main() { |
532 | | - test('Stream.fromIterable() emits the values in the iterable', () { |
533 | | - var stream = Stream.fromIterable([1, 2, 3]); |
534 | | -
|
535 | | - stream.listen(expectAsync1((number) { |
536 | | - expect(number, inInclusiveRange(1, 3)); |
537 | | - }, count: 3)); |
538 | | - }); |
539 | | -} |
540 | | -``` |
541 | | - |
542 | | -[`expectAsync()`]: https://pub.dev/documentation/test_api/latest/test_api/expectAsync.html |
543 | | - |
544 | | -### Stream Matchers |
545 | | - |
546 | | -The `test` package provides a suite of powerful matchers for dealing with |
547 | | -[asynchronous streams][Stream]. They're expressive and composable, and make it |
548 | | -easy to write complex expectations about the values emitted by a stream. For |
549 | | -example: |
550 | | - |
551 | | -[Stream]: https://api.dart.dev/stable/dart-async/Stream-class.html |
552 | | - |
553 | | -```dart |
554 | | -import 'dart:async'; |
555 | | -
|
556 | | -import 'package:test/test.dart'; |
557 | | -
|
558 | | -void main() { |
559 | | - test('process emits status messages', () { |
560 | | - // Dummy data to mimic something that might be emitted by a process. |
561 | | - var stdoutLines = Stream.fromIterable([ |
562 | | - 'Ready.', |
563 | | - 'Loading took 150ms.', |
564 | | - 'Succeeded!' |
565 | | - ]); |
566 | | -
|
567 | | - expect(stdoutLines, emitsInOrder([ |
568 | | - // Values match individual events. |
569 | | - 'Ready.', |
570 | | -
|
571 | | - // Matchers also run against individual events. |
572 | | - startsWith('Loading took'), |
573 | | -
|
574 | | - // Stream matchers can be nested. This asserts that one of two events are |
575 | | - // emitted after the "Loading took" line. |
576 | | - emitsAnyOf(['Succeeded!', 'Failed!']), |
577 | | -
|
578 | | - // By default, more events are allowed after the matcher finishes |
579 | | - // matching. This asserts instead that the stream emits a done event and |
580 | | - // nothing else. |
581 | | - emitsDone |
582 | | - ])); |
583 | | - }); |
584 | | -} |
585 | | -``` |
586 | | - |
587 | | -A stream matcher can also match the [`async`] package's [`StreamQueue`] class, |
588 | | -which allows events to be requested from a stream rather than pushed to the |
589 | | -consumer. The matcher will consume the matched events, but leave the rest of the |
590 | | -queue alone so that it can still be used by the test, unlike a normal `Stream` |
591 | | -which can only have one subscriber. For example: |
592 | | - |
593 | | -[`async`]: https://pub.dev/packages/async |
594 | | - |
595 | | -[`StreamQueue`]: https://pub.dev/documentation/async/latest/async/StreamQueue-class.html |
596 | | - |
597 | | -```dart |
598 | | -import 'dart:async'; |
599 | | -
|
600 | | -import 'package:async/async.dart'; |
601 | | -import 'package:test/test.dart'; |
602 | | -
|
603 | | -void main() { |
604 | | - test('process emits a WebSocket URL', () async { |
605 | | - // Wrap the Stream in a StreamQueue so that we can request events. |
606 | | - var stdout = StreamQueue(Stream.fromIterable([ |
607 | | - 'WebSocket URL:', |
608 | | - 'ws://localhost:1234/', |
609 | | - 'Waiting for connection...' |
610 | | - ])); |
611 | | -
|
612 | | - // Ignore lines from the process until it's about to emit the URL. |
613 | | - await expectLater(stdout, emitsThrough('WebSocket URL:')); |
614 | | -
|
615 | | - // Parse the next line as a URL. |
616 | | - var url = Uri.parse(await stdout.next); |
617 | | - expect(url.host, equals('localhost')); |
618 | | -
|
619 | | - // You can match against the same StreamQueue multiple times. |
620 | | - await expectLater(stdout, emits('Waiting for connection...')); |
621 | | - }); |
622 | | -} |
623 | | -``` |
624 | | - |
625 | | -The following built-in stream matchers are available: |
626 | | - |
627 | | -* [`emits()`] matches a single data event. |
628 | | -* [`emitsError()`] matches a single error event. |
629 | | -* [`emitsDone`] matches a single done event. |
630 | | -* [`mayEmit()`] consumes events if they match an inner matcher, without |
631 | | - requiring them to match. |
632 | | -* [`mayEmitMultiple()`] works like `mayEmit()`, but it matches events against |
633 | | - the matcher as many times as possible. |
634 | | -* [`emitsAnyOf()`] consumes events matching one (or more) of several possible |
635 | | - matchers. |
636 | | -* [`emitsInOrder()`] consumes events matching multiple matchers in a row. |
637 | | -* [`emitsInAnyOrder()`] works like `emitsInOrder()`, but it allows the matchers |
638 | | - to match in any order. |
639 | | -* [`neverEmits()`] matches a stream that finishes *without* matching an inner |
640 | | - matcher. |
641 | | - |
642 | | -You can also define your own custom stream matchers with [`StreamMatcher()`]. |
643 | | - |
644 | | -[`emits()`]: https://pub.dev/documentation/test_api/latest/expect/emits.html |
645 | | - |
646 | | -[`emitsError()`]: https://pub.dev/documentation/test_api/latest/expect/emitsError.html |
647 | | - |
648 | | -[`emitsDone`]: https://pub.dev/documentation/test_api/latest/expect/emitsDone.html |
649 | | - |
650 | | -[`mayEmit()`]: https://pub.dev/documentation/test_api/latest/expect/mayEmit.html |
651 | | - |
652 | | -[`mayEmitMultiple()`]: https://pub.dev/documentation/test_api/latest/expect/mayEmitMultiple.html |
653 | | - |
654 | | -[`emitsAnyOf()`]: https://pub.dev/documentation/test_api/latest/expect/emitsAnyOf.html |
655 | | - |
656 | | -[`emitsInOrder()`]: https://pub.dev/documentation/test_api/latest/expect/emitsInOrder.html |
657 | | - |
658 | | -[`emitsInAnyOrder()`]: https://pub.dev/documentation/test_api/latest/expect/emitsInAnyOrder.html |
659 | | - |
660 | | -[`neverEmits()`]: https://pub.dev/documentation/test_api/latest/expect/neverEmits.html |
661 | | - |
662 | | -[`StreamMatcher()`]: https://pub.dev/documentation/test_api/latest/expect/StreamMatcher-class.html |
663 | | - |
664 | 445 | ## Running Tests With Custom HTML |
665 | 446 |
|
666 | 447 | By default, the test runner will generate its own empty HTML file for browser |
|
0 commit comments