Line data Source code
1 : // Copyright (c) 2021, 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 : @Deprecated('package:test_core is not intended for general use. '
6 : 'Please use package:test.')
7 : library test_core.scaffolding;
8 :
9 : import 'dart:async';
10 :
11 : import 'package:meta/meta.dart' show isTest, isTestGroup;
12 : import 'package:path/path.dart' as p;
13 : import 'package:test_api/backend.dart'; //ignore: deprecated_member_use
14 : import 'package:test_api/scaffolding.dart' show Timeout, pumpEventQueue;
15 : import 'package:test_api/src/backend/declarer.dart'; // ignore: implementation_imports
16 : import 'package:test_api/src/backend/invoker.dart'; // ignore: implementation_imports
17 :
18 : import 'src/runner/engine.dart';
19 : import 'src/runner/plugin/environment.dart';
20 : import 'src/runner/reporter/expanded.dart';
21 : import 'src/runner/runner_suite.dart';
22 : import 'src/runner/suite.dart';
23 : import 'src/util/async.dart';
24 : import 'src/util/os.dart';
25 : import 'src/util/print_sink.dart';
26 :
27 : // Hide implementations which don't support being run directly.
28 : // This file is an almost direct copy of import below, but with the global
29 : // declarer added.
30 : export 'package:test_api/scaffolding.dart'
31 : hide test, group, setUp, setUpAll, tearDown, tearDownAll;
32 :
33 : /// The global declarer.
34 : ///
35 : /// This is used if a test file is run directly, rather than through the runner.
36 : Declarer? _globalDeclarer;
37 :
38 : /// Gets the declarer for the current scope.
39 : ///
40 : /// When using the runner, this returns the [Zone]-scoped declarer that's set by
41 : /// [RemoteListener]. If the test file is run directly, this returns
42 : /// [_globalDeclarer] (and sets it up on the first call).
43 11 : Declarer get _declarer {
44 11 : var declarer = Declarer.current;
45 : if (declarer != null) return declarer;
46 : if (_globalDeclarer != null) return _globalDeclarer!;
47 :
48 : // Since there's no Zone-scoped declarer, the test file is being run directly.
49 : // In order to run the tests, we set up our own Declarer via
50 : // [_globalDeclarer], and pump the event queue as a best effort to wait for
51 : // all tests to be defined before starting them.
52 0 : _globalDeclarer = Declarer();
53 :
54 0 : () async {
55 0 : await pumpEventQueue();
56 :
57 0 : var suite = RunnerSuite(const PluginEnvironment(), SuiteConfiguration.empty,
58 0 : _globalDeclarer!.build(), SuitePlatform(Runtime.vm, os: currentOSGuess),
59 0 : path: p.prettyUri(Uri.base));
60 :
61 0 : var engine = Engine();
62 0 : engine.suiteSink.add(suite);
63 0 : engine.suiteSink.close();
64 0 : ExpandedReporter.watch(engine, PrintSink(),
65 : color: true, printPath: false, printPlatform: false);
66 :
67 0 : var success = await runZoned(() => Invoker.guard(engine.run),
68 0 : zoneValues: {#test.declarer: _globalDeclarer});
69 0 : if (success == true) return null;
70 0 : print('');
71 0 : unawaited(Future.error('Dummy exception to set exit code.'));
72 : }();
73 :
74 : return _globalDeclarer!;
75 : }
76 :
77 : // TODO(nweiz): This and other top-level functions should throw exceptions if
78 : // they're called after the declarer has finished declaring.
79 : /// Creates a new test case with the given description (converted to a string)
80 : /// and body.
81 : ///
82 : /// The description will be added to the descriptions of any surrounding
83 : /// [group]s. If [testOn] is passed, it's parsed as a [platform selector][]; the
84 : /// test will only be run on matching platforms.
85 : ///
86 : /// [platform selector]: https://github.com/dart-lang/test/tree/master/pkgs/test#platform-selectors
87 : ///
88 : /// If [timeout] is passed, it's used to modify or replace the default timeout
89 : /// of 30 seconds. Timeout modifications take precedence in suite-group-test
90 : /// order, so [timeout] will also modify any timeouts set on the group or suite.
91 : ///
92 : /// If [skip] is a String or `true`, the test is skipped. If it's a String, it
93 : /// should explain why the test is skipped; this reason will be printed instead
94 : /// of running the test.
95 : ///
96 : /// If [tags] is passed, it declares user-defined tags that are applied to the
97 : /// test. These tags can be used to select or skip the test on the command line,
98 : /// or to do bulk test configuration. All tags should be declared in the
99 : /// [package configuration file][configuring tags]. The parameter can be an
100 : /// [Iterable] of tag names, or a [String] representing a single tag.
101 : ///
102 : /// If [retry] is passed, the test will be retried the provided number of times
103 : /// before being marked as a failure.
104 : ///
105 : /// [configuring tags]: https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#configuring-tags
106 : ///
107 : /// [onPlatform] allows tests to be configured on a platform-by-platform
108 : /// basis. It's a map from strings that are parsed as [PlatformSelector]s to
109 : /// annotation classes: [Timeout], [Skip], or lists of those. These
110 : /// annotations apply only on the given platforms. For example:
111 : ///
112 : /// test('potentially slow test', () {
113 : /// // ...
114 : /// }, onPlatform: {
115 : /// // This test is especially slow on Windows.
116 : /// 'windows': Timeout.factor(2),
117 : /// 'browser': [
118 : /// Skip('TODO: add browser support'),
119 : /// // This will be slow on browsers once it works on them.
120 : /// Timeout.factor(2)
121 : /// ]
122 : /// });
123 : ///
124 : /// If multiple platforms match, the annotations apply in order as through
125 : /// they were in nested groups.
126 : ///
127 : /// If the `solo` flag is `true`, only tests and groups marked as
128 : /// "solo" will be be run. This only restricts tests *within this test
129 : /// suite*—tests in other suites will run as normal. We recommend that users
130 : /// avoid this flag if possible and instead use the test runner flag `-n` to
131 : /// filter tests by name.
132 11 : @isTest
133 : void test(description, dynamic Function() body,
134 : {String? testOn,
135 : Timeout? timeout,
136 : skip,
137 : tags,
138 : Map<String, dynamic>? onPlatform,
139 : int? retry,
140 : @Deprecated('Debug only') bool solo = false}) {
141 33 : _declarer.test(description.toString(), body,
142 : testOn: testOn,
143 : timeout: timeout,
144 : skip: skip,
145 : onPlatform: onPlatform,
146 : tags: tags,
147 : retry: retry,
148 : solo: solo);
149 :
150 : // Force dart2js not to inline this function. We need it to be separate from
151 : // `main()` in JS stack traces in order to properly determine the line and
152 : // column where the test was defined. See sdk#26705.
153 : return;
154 : return; // ignore: dead_code
155 : }
156 :
157 : /// Creates a group of tests.
158 : ///
159 : /// A group's description (converted to a string) is included in the descriptions
160 : /// of any tests or sub-groups it contains. [setUp] and [tearDown] are also scoped
161 : /// to the containing group.
162 : ///
163 : /// If [testOn] is passed, it's parsed as a [platform selector][]; the test will
164 : /// only be run on matching platforms.
165 : ///
166 : /// [platform selector]: https://github.com/dart-lang/test/tree/master/pkgs/test#platform-selectors
167 : ///
168 : /// If [timeout] is passed, it's used to modify or replace the default timeout
169 : /// of 30 seconds. Timeout modifications take precedence in suite-group-test
170 : /// order, so [timeout] will also modify any timeouts set on the suite, and will
171 : /// be modified by any timeouts set on individual tests.
172 : ///
173 : /// If [skip] is a String or `true`, the group is skipped. If it's a String, it
174 : /// should explain why the group is skipped; this reason will be printed instead
175 : /// of running the group's tests.
176 : ///
177 : /// If [tags] is passed, it declares user-defined tags that are applied to the
178 : /// test. These tags can be used to select or skip the test on the command line,
179 : /// or to do bulk test configuration. All tags should be declared in the
180 : /// [package configuration file][configuring tags]. The parameter can be an
181 : /// [Iterable] of tag names, or a [String] representing a single tag.
182 : ///
183 : /// [configuring tags]: https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#configuring-tags
184 : ///
185 : /// [onPlatform] allows groups to be configured on a platform-by-platform
186 : /// basis. It's a map from strings that are parsed as [PlatformSelector]s to
187 : /// annotation classes: [Timeout], [Skip], or lists of those. These
188 : /// annotations apply only on the given platforms. For example:
189 : ///
190 : /// group('potentially slow tests', () {
191 : /// // ...
192 : /// }, onPlatform: {
193 : /// // These tests are especially slow on Windows.
194 : /// 'windows': Timeout.factor(2),
195 : /// 'browser': [
196 : /// Skip('TODO: add browser support'),
197 : /// // They'll be slow on browsers once it works on them.
198 : /// Timeout.factor(2)
199 : /// ]
200 : /// });
201 : ///
202 : /// If multiple platforms match, the annotations apply in order as through
203 : /// they were in nested groups.
204 : ///
205 : /// If the `solo` flag is `true`, only tests and groups marked as
206 : /// "solo" will be be run. This only restricts tests *within this test
207 : /// suite*—tests in other suites will run as normal. We recommend that users
208 : /// avoid this flag if possible, and instead use the test runner flag `-n` to
209 : /// filter tests by name.
210 2 : @isTestGroup
211 : void group(description, dynamic Function() body,
212 : {String? testOn,
213 : Timeout? timeout,
214 : skip,
215 : tags,
216 : Map<String, dynamic>? onPlatform,
217 : int? retry,
218 : @Deprecated('Debug only') bool solo = false}) {
219 6 : _declarer.group(description.toString(), body,
220 : testOn: testOn,
221 : timeout: timeout,
222 : skip: skip,
223 : tags: tags,
224 : onPlatform: onPlatform,
225 : retry: retry,
226 : solo: solo);
227 :
228 : // Force dart2js not to inline this function. We need it to be separate from
229 : // `main()` in JS stack traces in order to properly determine the line and
230 : // column where the test was defined. See sdk#26705.
231 : return;
232 : return; // ignore: dead_code
233 : }
234 :
235 : /// Registers a function to be run before tests.
236 : ///
237 : /// This function will be called before each test is run. [callback] may be
238 : /// asynchronous; if so, it must return a [Future].
239 : ///
240 : /// If this is called within a test group, it applies only to tests in that
241 : /// group. [callback] will be run after any set-up callbacks in parent groups or
242 : /// at the top level.
243 : ///
244 : /// Each callback at the top level or in a given group will be run in the order
245 : /// they were declared.
246 9 : void setUp(dynamic Function() callback) => _declarer.setUp(callback);
247 :
248 : /// Registers a function to be run after tests.
249 : ///
250 : /// This function will be called after each test is run. [callback] may be
251 : /// asynchronous; if so, it must return a [Future].
252 : ///
253 : /// If this is called within a test group, it applies only to tests in that
254 : /// group. [callback] will be run before any tear-down callbacks in parent
255 : /// groups or at the top level.
256 : ///
257 : /// Each callback at the top level or in a given group will be run in the
258 : /// reverse of the order they were declared.
259 : ///
260 : /// See also [addTearDown], which adds tear-downs to a running test.
261 9 : void tearDown(dynamic Function() callback) => _declarer.tearDown(callback);
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(dynamic Function() 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(dynamic Function() callback) =>
290 0 : _declarer.tearDownAll(callback);
|