Line data Source code
1 : // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 : // for details. All rights reserved. Use of this source code is governed by a
3 : // BSD-style license that can be found in the LICENSE file.
4 :
5 : import 'dart:async';
6 :
7 : import 'package:path/path.dart' as p;
8 :
9 : import 'src/backend/declarer.dart';
10 : import 'src/backend/invoker.dart';
11 : import 'src/backend/test_platform.dart';
12 : import 'src/frontend/timeout.dart';
13 : import 'src/runner/configuration/suite.dart';
14 : import 'src/runner/engine.dart';
15 : import 'src/runner/plugin/environment.dart';
16 : import 'src/runner/reporter/expanded.dart';
17 : import 'src/runner/runner_suite.dart';
18 : import 'src/utils.dart';
19 :
20 : export 'package:matcher/matcher.dart';
21 :
22 : export 'src/frontend/expect.dart' hide formatFailure;
23 : export 'src/frontend/expect_async.dart';
24 : export 'src/frontend/future_matchers.dart';
25 : export 'src/frontend/on_platform.dart';
26 : export 'src/frontend/prints_matcher.dart';
27 : export 'src/frontend/skip.dart';
28 : export 'src/frontend/spawn_hybrid.dart';
29 : export 'src/frontend/stream_matcher.dart';
30 : export 'src/frontend/stream_matchers.dart';
31 : export 'src/frontend/tags.dart';
32 : export 'src/frontend/test_on.dart';
33 : export 'src/frontend/throws_matcher.dart';
34 : export 'src/frontend/throws_matchers.dart';
35 : export 'src/frontend/timeout.dart';
36 :
37 : /// The global declarer.
38 : ///
39 : /// This is used if a test file is run directly, rather than through the runner.
40 : Declarer _globalDeclarer;
41 :
42 : /// Gets the declarer for the current scope.
43 : ///
44 : /// When using the runner, this returns the [Zone]-scoped declarer that's set by
45 : /// [IsolateListener] or [IframeListener]. If the test file is run directly,
46 : /// this returns [_globalDeclarer] (and sets it up on the first call).
47 : Declarer get _declarer {
48 5 : var declarer = Declarer.current;
49 : if (declarer != null) return declarer;
50 : if (_globalDeclarer != null) return _globalDeclarer;
51 :
52 : // Since there's no Zone-scoped declarer, the test file is being run directly.
53 : // In order to run the tests, we set up our own Declarer via
54 : // [_globalDeclarer], and schedule a microtask to run the tests once they're
55 : // finished being defined.
56 5 : _globalDeclarer = new Declarer();
57 5 : scheduleMicrotask(() async {
58 5 : var suite = new RunnerSuite(const PluginEnvironment(),
59 10 : SuiteConfiguration.empty, _globalDeclarer.build(),
60 10 : path: p.prettyUri(Uri.base),
61 : platform: TestPlatform.vm,
62 5 : os: currentOSGuess);
63 :
64 5 : var engine = new Engine();
65 10 : engine.suiteSink.add(suite);
66 10 : engine.suiteSink.close();
67 5 : ExpandedReporter.watch(engine,
68 : color: true, printPath: false, printPlatform: false);
69 :
70 10 : var success = await engine.run();
71 : // TODO(nweiz): Set the exit code on the VM when issue 6943 is fixed.
72 : if (success) return null;
73 0 : print('');
74 0 : new Future.error("Dummy exception to set exit code.");
75 0 : });
76 : return _globalDeclarer;
77 : }
78 :
79 : // TODO(nweiz): This and other top-level functions should throw exceptions if
80 : // they're called after the declarer has finished declaring.
81 : /// Creates a new test case with the given description (converted to a string)
82 : /// and body.
83 : ///
84 : /// The description will be added to the descriptions of any surrounding
85 : /// [group]s. If [testOn] is passed, it's parsed as a [platform selector][]; the
86 : /// test will only be run on matching platforms.
87 : ///
88 : /// [platform selector]: https://github.com/dart-lang/test/#platform-selector-syntax
89 : ///
90 : /// If [timeout] is passed, it's used to modify or replace the default timeout
91 : /// of 30 seconds. Timeout modifications take precedence in suite-group-test
92 : /// order, so [timeout] will also modify any timeouts set on the group or suite.
93 : ///
94 : /// If [skip] is a String or `true`, the test is skipped. If it's a String, it
95 : /// should explain why the test is skipped; this reason will be printed instead
96 : /// of running the test.
97 : ///
98 : /// If [tags] is passed, it declares user-defined tags that are applied to the
99 : /// test. These tags can be used to select or skip the test on the command line,
100 : /// or to do bulk test configuration. All tags should be declared in the
101 : /// [package configuration file][configuring tags]. The parameter can be an
102 : /// [Iterable] of tag names, or a [String] representing a single tag.
103 : ///
104 : /// If [retry] is passed, the test will be retried the provided number of times
105 : /// before being marked as a failure.
106 : ///
107 : /// [configuring tags]: https://github.com/dart-lang/test/blob/master/doc/package_config.md#configuring-tags
108 : ///
109 : /// [onPlatform] allows tests to be configured on a platform-by-platform
110 : /// basis. It's a map from strings that are parsed as [PlatformSelector]s to
111 : /// annotation classes: [Timeout], [Skip], or lists of those. These
112 : /// annotations apply only on the given platforms. For example:
113 : ///
114 : /// test("potentially slow test", () {
115 : /// // ...
116 : /// }, onPlatform: {
117 : /// // This test is especially slow on Windows.
118 : /// "windows": new Timeout.factor(2),
119 : /// "browser": [
120 : /// new Skip("TODO: add browser support"),
121 : /// // This will be slow on browsers once it works on them.
122 : /// new Timeout.factor(2)
123 : /// ]
124 : /// });
125 : ///
126 : /// If multiple platforms match, the annotations apply in order as through
127 : /// they were in nested groups.
128 : void test(description, body(),
129 : {String testOn,
130 : Timeout timeout,
131 : skip,
132 : tags,
133 : Map<String, dynamic> onPlatform,
134 : int retry}) {
135 15 : _declarer.test(description.toString(), body,
136 : testOn: testOn,
137 : timeout: timeout,
138 : skip: skip,
139 : onPlatform: onPlatform,
140 : tags: tags,
141 : retry: retry);
142 :
143 : // Force dart2js not to inline this function. We need it to be separate from
144 : // `main()` in JS stack traces in order to properly determine the line and
145 : // column where the test was defined. See sdk#26705.
146 : return;
147 : return; // ignore: dead_code
148 : }
149 :
150 : /// Creates a group of tests.
151 : ///
152 : /// A group's description (converted to a string) is included in the descriptions
153 : /// of any tests or sub-groups it contains. [setUp] and [tearDown] are also scoped
154 : /// to the containing group.
155 : ///
156 : /// If [testOn] is passed, it's parsed as a [platform selector][]; the test will
157 : /// only be run on matching platforms.
158 : ///
159 : /// [platform selector]: https://github.com/dart-lang/test/#platform-selector-syntax
160 : ///
161 : /// If [timeout] is passed, it's used to modify or replace the default timeout
162 : /// of 30 seconds. Timeout modifications take precedence in suite-group-test
163 : /// order, so [timeout] will also modify any timeouts set on the suite, and will
164 : /// be modified by any timeouts set on individual tests.
165 : ///
166 : /// If [skip] is a String or `true`, the group is skipped. If it's a String, it
167 : /// should explain why the group is skipped; this reason will be printed instead
168 : /// of running the group's tests.
169 : ///
170 : /// If [tags] is passed, it declares user-defined tags that are applied to the
171 : /// test. These tags can be used to select or skip the test on the command line,
172 : /// or to do bulk test configuration. All tags should be declared in the
173 : /// [package configuration file][configuring tags]. The parameter can be an
174 : /// [Iterable] of tag names, or a [String] representing a single tag.
175 : ///
176 : /// [configuring tags]: https://github.com/dart-lang/test/blob/master/doc/package_config.md#configuring-tags
177 : ///
178 : /// [onPlatform] allows groups to be configured on a platform-by-platform
179 : /// basis. It's a map from strings that are parsed as [PlatformSelector]s to
180 : /// annotation classes: [Timeout], [Skip], or lists of those. These
181 : /// annotations apply only on the given platforms. For example:
182 : ///
183 : /// group("potentially slow tests", () {
184 : /// // ...
185 : /// }, onPlatform: {
186 : /// // These tests are especially slow on Windows.
187 : /// "windows": new Timeout.factor(2),
188 : /// "browser": [
189 : /// new Skip("TODO: add browser support"),
190 : /// // They'll be slow on browsers once it works on them.
191 : /// new Timeout.factor(2)
192 : /// ]
193 : /// });
194 : ///
195 : /// If multiple platforms match, the annotations apply in order as through
196 : /// they were in nested groups.
197 : void group(description, body(),
198 : {String testOn,
199 : Timeout timeout,
200 : skip,
201 : tags,
202 : Map<String, dynamic> onPlatform,
203 : int retry}) {
204 15 : _declarer.group(description.toString(), body,
205 : testOn: testOn,
206 : timeout: timeout,
207 : skip: skip,
208 : tags: tags,
209 : onPlatform: onPlatform,
210 : retry: retry);
211 :
212 : // Force dart2js not to inline this function. We need it to be separate from
213 : // `main()` in JS stack traces in order to properly determine the line and
214 : // column where the test was defined. See sdk#26705.
215 : return;
216 : return; // ignore: dead_code
217 : }
218 :
219 : /// Registers a function to be run before tests.
220 : ///
221 : /// This function will be called before each test is run. [callback] may be
222 : /// asynchronous; if so, it must return a [Future].
223 : ///
224 : /// If this is called within a test group, it applies only to tests in that
225 : /// group. [callback] will be run after any set-up callbacks in parent groups or
226 : /// at the top level.
227 : ///
228 : /// Each callback at the top level or in a given group will be run in the order
229 : /// they were declared.
230 10 : void setUp(callback()) => _declarer.setUp(callback);
231 :
232 : /// Registers a function to be run after tests.
233 : ///
234 : /// This function will be called after each test is run. [callback] may be
235 : /// asynchronous; if so, it must return a [Future].
236 : ///
237 : /// If this is called within a test group, it applies only to tests in that
238 : /// group. [callback] will be run before any tear-down callbacks in parent
239 : /// groups or at the top level.
240 : ///
241 : /// Each callback at the top level or in a given group will be run in the
242 : /// reverse of the order they were declared.
243 : ///
244 : /// See also [addTearDown], which adds tear-downs to a running test.
245 0 : void tearDown(callback()) => _declarer.tearDown(callback);
246 :
247 : /// Registers a function to be run after the current test.
248 : ///
249 : /// This is called within a running test, and adds a tear-down only for the
250 : /// current test. It allows testing libraries to add cleanup logic as soon as
251 : /// there's something to clean up.
252 : ///
253 : /// The [callback] is run before any callbacks registered with [tearDown]. Like
254 : /// [tearDown], the most recently registered callback is run first.
255 : void addTearDown(callback()) {
256 0 : if (Invoker.current == null) {
257 0 : throw new StateError("addTearDown() may only be called within a test.");
258 : }
259 :
260 0 : Invoker.current.addTearDown(callback);
261 : }
262 :
263 : /// Registers a function to be run once before all tests.
264 : ///
265 : /// [callback] may be asynchronous; if so, it must return a [Future].
266 : ///
267 : /// If this is called within a test group, [callback] will run before all tests
268 : /// in that group. It will be run after any [setUpAll] callbacks in parent
269 : /// groups or at the top level. It won't be run if none of the tests in the
270 : /// group are run.
271 : ///
272 : /// **Note**: This function makes it very easy to accidentally introduce hidden
273 : /// dependencies between tests that should be isolated. In general, you should
274 : /// prefer [setUp], and only use [setUpAll] if the callback is prohibitively
275 : /// slow.
276 0 : void setUpAll(callback()) => _declarer.setUpAll(callback);
277 :
278 : /// Registers a function to be run once after all tests.
279 : ///
280 : /// If this is called within a test group, [callback] will run after all tests
281 : /// in that group. It will be run before any [tearDownAll] callbacks in parent
282 : /// groups or at the top level. It won't be run if none of the tests in the
283 : /// group are run.
284 : ///
285 : /// **Note**: This function makes it very easy to accidentally introduce hidden
286 : /// dependencies between tests that should be isolated. In general, you should
287 : /// prefer [tearDown], and only use [tearDownAll] if the callback is
288 : /// prohibitively slow.
289 0 : void tearDownAll(callback()) => _declarer.tearDownAll(callback);
290 :
291 : /// Registers an exception that was caught for the current test.
292 : void registerException(error, [StackTrace stackTrace]) {
293 : // This will usually forward directly to [Invoker.current.handleError], but
294 : // going through the zone API allows other zones to consistently see errors.
295 0 : Zone.current.handleUncaughtError(error, stackTrace);
296 : }
297 :
298 : /// Prints [message] if and when the current test fails.
299 : ///
300 : /// This is intended for test infrastructure to provide debugging information
301 : /// without cluttering the output for successful tests. Note that unlike
302 : /// [print], each individual message passed to [printOnFailure] will be
303 : /// separated by a blank line.
304 0 : void printOnFailure(String message) => Invoker.current.printOnFailure(message);
|