| OLD | NEW |
| 1 Support for writing unit tests in Dart. | 1 `unittest` provides a standard way of writing and running tests in Dart. |
| 2 | 2 |
| 3 **See also:** | 3 ## Writing Tests |
| 4 [Unit Testing with Dart] | |
| 5 (http://www.dartlang.org/articles/dart-unit-tests/) | |
| 6 | 4 |
| 7 ##Concepts | 5 Tests are specified using the top-level [`test()`][test] function, and test |
| 6 assertions are made using [`expect()`][expect]: |
| 8 | 7 |
| 9 * __Tests__: Tests are specified via the top-level function [test], they can be | 8 [test]: http://www.dartdocs.org/documentation/unittest/latest/index.html#unittes
t/unittest@id_test |
| 10 organized together using [group]. | 9 [expect]: http://www.dartdocs.org/documentation/unittest/latest/index.html#unitt
est/unittest@id_expect |
| 11 | |
| 12 * __Checks__: Test expectations can be specified via [expect] | |
| 13 | |
| 14 * __Matchers__: [expect] assertions are written declaratively using the | |
| 15 [Matcher] class. | |
| 16 | |
| 17 * __Configuration__: The framework can be adapted by setting | |
| 18 [unittestConfiguration] with a [Configuration]. See the other libraries | |
| 19 in the `unittest` package for alternative implementations of | |
| 20 [Configuration] including `compact_vm_config.dart`, `html_config.dart` | |
| 21 and `html_enhanced_config.dart`. | |
| 22 | |
| 23 ##Examples | |
| 24 | |
| 25 A trivial test: | |
| 26 | 10 |
| 27 ```dart | 11 ```dart |
| 28 import 'package:unittest/unittest.dart'; | 12 import "package:unittest/unittest.dart"; |
| 29 | 13 |
| 30 void main() { | 14 void main() { |
| 31 test('this is a test', () { | 15 test("String.split() splits the string on the delimiter", () { |
| 32 int x = 2 + 3; | 16 var string = "foo,bar,baz"; |
| 33 expect(x, equals(5)); | 17 expect(string.split(","), equals(["foo", "bar", "baz"])); |
| 18 }); |
| 19 |
| 20 test("String.trim() removes surrounding whitespace", () { |
| 21 var string = " foo "; |
| 22 expect(string.trim(), equals("foo")); |
| 34 }); | 23 }); |
| 35 } | 24 } |
| 36 ``` | 25 ``` |
| 37 | 26 |
| 38 Multiple tests: | 27 Tests can be grouped together using the [`group()`] function. Each group's |
| 28 description is added to the beginning of its test's descriptions. |
| 39 | 29 |
| 40 ```dart | 30 ```dart |
| 41 import 'package:unittest/unittest.dart'; | 31 import "package:unittest/unittest.dart"; |
| 42 | 32 |
| 43 void main() { | 33 void main() { |
| 44 test('this is a test', () { | 34 group("String", () { |
| 45 int x = 2 + 3; | 35 test(".split() splits the string on the delimiter", () { |
| 46 expect(x, equals(5)); | 36 var string = "foo,bar,baz"; |
| 47 }); | 37 expect(string.split(","), equals(["foo", "bar", "baz"])); |
| 48 test('this is another test', () { | 38 }); |
| 49 int x = 2 + 3; | |
| 50 expect(x, equals(5)); | |
| 51 }); | |
| 52 } | |
| 53 ``` | |
| 54 | 39 |
| 55 Multiple tests, grouped by category: | 40 test(".trim() removes surrounding whitespace", () { |
| 56 | 41 var string = " foo "; |
| 57 ```dart | 42 expect(string.trim(), equals("foo")); |
| 58 import 'package:unittest/unittest.dart'; | |
| 59 | |
| 60 void main() { | |
| 61 group('group A', () { | |
| 62 test('test A.1', () { | |
| 63 int x = 2 + 3; | |
| 64 expect(x, equals(5)); | |
| 65 }); | |
| 66 test('test A.2', () { | |
| 67 int x = 2 + 3; | |
| 68 expect(x, equals(5)); | |
| 69 }); | 43 }); |
| 70 }); | 44 }); |
| 71 group('group B', () { | 45 |
| 72 test('this B.1', () { | 46 group("int", () { |
| 73 int x = 2 + 3; | 47 test(".remainder() returns the remainder of division", () { |
| 74 expect(x, equals(5)); | 48 expect(11.remainder(3), equals(2)); |
| 49 }); |
| 50 |
| 51 test(".toRadixString() returns a hex string", () { |
| 52 expect(11.toRadixString(16), equals("b")); |
| 75 }); | 53 }); |
| 76 }); | 54 }); |
| 77 } | 55 } |
| 78 ``` | 56 ``` |
| 79 | 57 |
| 80 Asynchronous tests: if callbacks expect between 0 and 6 positional | 58 Any matchers from the [`matcher`][matcher] package can be used with `expect()` |
| 81 arguments, [expectAsync] will wrap a function into a new callback and will | 59 to do complex validations: |
| 82 not consider the test complete until that callback is run. A count argument | 60 |
| 83 can be provided to specify the number of times the callback should be called | 61 [matcher]: http://www.dartdocs.org/documentation/matcher/latest/index.html#match
er/matcher |
| 84 (the default is 1). | |
| 85 | 62 |
| 86 ```dart | 63 ```dart |
| 87 import 'dart:async'; | 64 import "package:unittest/unittest.dart"; |
| 88 import 'package:unittest/unittest.dart'; | |
| 89 | 65 |
| 90 void main() { | 66 void main() { |
| 91 test('callback is executed once', () { | 67 test(".split() splits the string on the delimiter", () { |
| 92 // wrap the callback of an asynchronous call with [expectAsync] if | 68 expect("foo,bar,baz", allOf([ |
| 93 // the callback takes 0 arguments... | 69 contains("foo"), |
| 94 Timer.run(expectAsync(() { | 70 isNot(startsWith("bar")), |
| 95 int x = 2 + 3; | 71 endsWith("baz") |
| 96 expect(x, equals(5)); | 72 ])); |
| 97 })); | |
| 98 }); | |
| 99 | |
| 100 test('callback is executed twice', () { | |
| 101 var callback = expectAsync(() { | |
| 102 int x = 2 + 3; | |
| 103 expect(x, equals(5)); | |
| 104 }, count: 2); // <-- we can indicate multiplicity to [expectAsync] | |
| 105 Timer.run(callback); | |
| 106 Timer.run(callback); | |
| 107 }); | 73 }); |
| 108 } | 74 } |
| 109 ``` | 75 ``` |
| 110 | 76 |
| 111 There may be times when the number of times a callback should be called is | 77 ## Running Tests |
| 112 non-deterministic. In this case a dummy callback can be created with | |
| 113 expectAsync((){}) and this can be called from the real callback when it is | |
| 114 finally complete. | |
| 115 | 78 |
| 116 A variation on this is [expectAsyncUntil], which takes a callback as the | 79 A single test file can be run just using `dart path/to/test.dart`. |
| 117 first parameter and a predicate function as the second parameter. After each | |
| 118 time the callback is called, the predicate function will be called. If it | |
| 119 returns `false` the test will still be considered incomplete. | |
| 120 | 80 |
| 121 Test functions can return [Future]s, which provide another way of doing | 81  |
| 122 asynchronous tests. The test framework will handle exceptions thrown by | 82 |
| 123 the Future, and will advance to the next test when the Future is complete. | 83 Many tests can be run at a time using `pub run unittest:unittest path/to/dir`. |
| 84 |
| 85  |
| 86 |
| 87 `unittest` considers any file that ends with `_test.dart` to be a test file. If |
| 88 you don't pass any paths, it will run all the test files in your `test/` |
| 89 directory, making it easy to test your entire application at once. |
| 90 |
| 91 By default, tests are run in the Dart VM, but you can run them in the browser as |
| 92 well by passing `pub run unittest:unittest -p chrome path/to/test.dart`. |
| 93 `unittest` will take care of starting the browser and loading the tests, and all |
| 94 the results will be reported on the command line just like for VM tests. In |
| 95 fact, you can even run tests on both platforms with a single command: `pub run |
| 96 unittest:unittest -p chrome -p vm path/to/test.dart`. |
| 97 |
| 98 ## Asynchronous Tests |
| 99 |
| 100 Tests written with `async`/`await` will work automatically. The test runner |
| 101 won't consider the test finished until the returned `Future` completes. |
| 124 | 102 |
| 125 ```dart | 103 ```dart |
| 126 import 'dart:async'; | 104 import "dart:async"; |
| 127 import 'package:unittest/unittest.dart'; | 105 |
| 106 import "package:unittest/unittest.dart"; |
| 128 | 107 |
| 129 void main() { | 108 void main() { |
| 130 test('test that time has passed', () { | 109 test("new Future.value() returns the value", () async { |
| 131 var duration = const Duration(milliseconds: 200); | 110 var value = await new Future.value(10); |
| 132 var time = new DateTime.now(); | 111 expect(value, equals(10)); |
| 133 | |
| 134 return new Future.delayed(duration).then((_) { | |
| 135 var delta = new DateTime.now().difference(time); | |
| 136 | |
| 137 expect(delta, greaterThanOrEqualTo(duration)); | |
| 138 }); | |
| 139 }); | 112 }); |
| 140 } | 113 } |
| 141 ``` | 114 ``` |
| 115 |
| 116 There are also a number of useful functions and matchers for more advanced |
| 117 asynchrony. The [`completion()`][completion] matcher can be used to test |
| 118 `Futures`; it ensures that the test doesn't finish until the `Future` completes, |
| 119 and runs a matcher against that `Future`'s value. |
| 120 |
| 121 [completion]: http://www.dartdocs.org/documentation/unittest/latest/index.html#u
nittest/unittest@id_completion |
| 122 |
| 123 ```dart |
| 124 import "dart:async"; |
| 125 |
| 126 import "package:unittest/unittest.dart"; |
| 127 |
| 128 void main() { |
| 129 test("new Future.value() returns the value", () { |
| 130 expect(new Future.value(10), completion(equals(10))); |
| 131 }); |
| 132 } |
| 133 ``` |
| 134 |
| 135 The [`throwsA()`][throwsA] matcher and the various `throwsExceptionType` |
| 136 matchers work with both synchronous callbacks and asynchronous `Future`s. They |
| 137 ensure that a particular type of exception is thrown: |
| 138 |
| 139 [completion]: http://www.dartdocs.org/documentation/unittest/latest/index.html#u
nittest/unittest@id_throwsA |
| 140 |
| 141 ```dart |
| 142 import "dart:async"; |
| 143 |
| 144 import "package:unittest/unittest.dart"; |
| 145 |
| 146 void main() { |
| 147 test("new Future.error() throws the error", () { |
| 148 expect(new Future.error("oh no"), throwsA(equals("oh no"))); |
| 149 expect(new Future.error(new StateError("bad state")), throwsStateError); |
| 150 }); |
| 151 } |
| 152 ``` |
| 153 |
| 154 The [`expectAsync()`][expectAsync] function wraps another function and has two |
| 155 jobs. First, it asserts that the wrapped function is called a certain number of |
| 156 times, and will cause the test to fail if it's called too often; second, it |
| 157 keeps the test from finishing until the function is called the requisite number |
| 158 of times. |
| 159 |
| 160 ```dart |
| 161 import "dart:async"; |
| 162 |
| 163 import "package:unittest/unittest.dart"; |
| 164 |
| 165 void main() { |
| 166 test("Stream.fromIterable() emits the values in the iterable", () { |
| 167 var stream = new Stream.fromIterable([1, 2, 3]); |
| 168 |
| 169 stream.listen(expectAsync((number) { |
| 170 expect(number, inInclusiveRange(1, 3)); |
| 171 }, count: 3)); |
| 172 }); |
| 173 } |
| 174 ``` |
| 175 |
| 176 [expectAsync]: http://www.dartdocs.org/documentation/unittest/latest/index.html#
unittest/unittest@id_expectAsync |
| OLD | NEW |