| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // TODO(nweiz): Add support for calling [schedule] while the schedule is already | 5 // TODO(nweiz): Add support for calling [schedule] while the schedule is already |
| 6 // running. | 6 // running. |
| 7 // TODO(nweiz): Port the non-Pub-specific scheduled test libraries from Pub. | 7 // TODO(nweiz): Port the non-Pub-specific scheduled test libraries from Pub. |
| 8 /// A package for writing readable tests of asynchronous behavior. | 8 /// A package for writing readable tests of asynchronous behavior. |
| 9 /// | 9 /// |
| 10 /// ## Installing ## | 10 /// ## Installing ## |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 /// If a single task might take a long time, you can also manually tell the | 184 /// If a single task might take a long time, you can also manually tell the |
| 185 /// [Schedule] that it's making progress by calling [Schedule.heartbeat], which | 185 /// [Schedule] that it's making progress by calling [Schedule.heartbeat], which |
| 186 /// will reset the timeout whenever it's called. | 186 /// will reset the timeout whenever it's called. |
| 187 /// | 187 /// |
| 188 /// [pub]: http://pub.dartlang.org | 188 /// [pub]: http://pub.dartlang.org |
| 189 /// [pkg]: http://pub.dartlang.org/packages/scheduled_test | 189 /// [pkg]: http://pub.dartlang.org/packages/scheduled_test |
| 190 library scheduled_test; | 190 library scheduled_test; |
| 191 | 191 |
| 192 import 'dart:async'; | 192 import 'dart:async'; |
| 193 | 193 |
| 194 import 'package:stack_trace/stack_trace.dart'; |
| 194 import 'package:unittest/unittest.dart' as unittest; | 195 import 'package:unittest/unittest.dart' as unittest; |
| 195 | 196 |
| 196 import 'src/schedule.dart'; | 197 import 'src/schedule.dart'; |
| 197 import 'src/schedule_error.dart'; | 198 import 'src/schedule_error.dart'; |
| 198 | 199 |
| 199 export 'package:unittest/unittest.dart' hide | 200 export 'package:unittest/unittest.dart' hide |
| 200 test, solo_test, group, setUp, tearDown, completes, completion; | 201 test, solo_test, group, setUp, tearDown, completes, completion; |
| 201 | 202 |
| 202 export 'src/schedule.dart'; | 203 export 'src/schedule.dart'; |
| 203 export 'src/schedule_error.dart'; | 204 export 'src/schedule_error.dart'; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 223 /// Creates a new test case with the given description and body that will be the | 224 /// Creates a new test case with the given description and body that will be the |
| 224 /// only test run in this file. This has the same semantics as | 225 /// only test run in this file. This has the same semantics as |
| 225 /// [unittest.solo_test]. | 226 /// [unittest.solo_test]. |
| 226 void solo_test(String description, void body()) => | 227 void solo_test(String description, void body()) => |
| 227 _test(description, body, unittest.solo_test); | 228 _test(description, body, unittest.solo_test); |
| 228 | 229 |
| 229 void _test(String description, void body(), Function testFn) { | 230 void _test(String description, void body(), Function testFn) { |
| 230 _ensureInitialized(); | 231 _ensureInitialized(); |
| 231 _ensureSetUpForTopLevel(); | 232 _ensureSetUpForTopLevel(); |
| 232 testFn(description, () { | 233 testFn(description, () { |
| 233 var asyncDone = unittest.expectAsync0(() {}); | 234 var completer = new Completer(); |
| 234 return currentSchedule.run(() { | 235 |
| 235 if (_setUpFn != null) _setUpFn(); | 236 Chain.capture(() { |
| 236 body(); | 237 _currentSchedule = new Schedule(); |
| 237 }).then((_) { | 238 return currentSchedule.run(() { |
| 238 // If we got here, the test completed successfully so tell unittest so. | 239 if (_setUpFn != null) _setUpFn(); |
| 239 asyncDone(); | 240 body(); |
| 240 }).catchError((e) { | 241 }).then(completer.complete); |
| 242 }, onError: (e, chain) { |
| 241 if (e is ScheduleError) { | 243 if (e is ScheduleError) { |
| 242 assert(e.schedule.errors.contains(e)); | 244 assert(e.schedule.errors.contains(e)); |
| 243 assert(e.schedule == currentSchedule); | 245 assert(e.schedule == currentSchedule); |
| 244 unittest.registerException(e.schedule.errorString()); | 246 unittest.registerException(e.schedule.errorString()); |
| 245 } else { | 247 } else { |
| 246 unittest.registerException(e); | 248 unittest.registerException(e, chain); |
| 247 } | 249 } |
| 250 completer.complete(); |
| 248 }); | 251 }); |
| 252 |
| 253 return completer.future; |
| 249 }); | 254 }); |
| 250 } | 255 } |
| 251 | 256 |
| 252 /// Whether or not the tests currently being defined are in a group. This is | 257 /// Whether or not the tests currently being defined are in a group. This is |
| 253 /// only true when defining tests, not when executing them. | 258 /// only true when defining tests, not when executing them. |
| 254 bool _inGroup = false; | 259 bool _inGroup = false; |
| 255 | 260 |
| 256 /// Creates a new named group of tests. This has the same semantics as | 261 /// Creates a new named group of tests. This has the same semantics as |
| 257 /// [unittest.group]. | 262 /// [unittest.group]. |
| 258 void group(String description, void body()) { | 263 void group(String description, void body()) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 /// Registers callbacks for [unittest.setUp] and [unittest.tearDown] that set up | 315 /// Registers callbacks for [unittest.setUp] and [unittest.tearDown] that set up |
| 311 /// and tear down the scheduled test infrastructure. | 316 /// and tear down the scheduled test infrastructure. |
| 312 void _setUpScheduledTest([void setUpFn()]) { | 317 void _setUpScheduledTest([void setUpFn()]) { |
| 313 if (!_inGroup) { | 318 if (!_inGroup) { |
| 314 _setUpForTopLevel = true; | 319 _setUpForTopLevel = true; |
| 315 unittest.setUp(() { | 320 unittest.setUp(() { |
| 316 if (currentSchedule != null) { | 321 if (currentSchedule != null) { |
| 317 throw new StateError('There seems to be another scheduled test ' | 322 throw new StateError('There seems to be another scheduled test ' |
| 318 'still running.'); | 323 'still running.'); |
| 319 } | 324 } |
| 320 _currentSchedule = new Schedule(); | |
| 321 if (_setUpFn != null) { | 325 if (_setUpFn != null) { |
| 322 var parentFn = _setUpFn; | 326 var parentFn = _setUpFn; |
| 323 _setUpFn = () { parentFn(); setUpFn(); }; | 327 _setUpFn = () { parentFn(); setUpFn(); }; |
| 324 } else { | 328 } else { |
| 325 _setUpFn = setUpFn; | 329 _setUpFn = setUpFn; |
| 326 } | 330 } |
| 327 }); | 331 }); |
| 328 | 332 |
| 329 unittest.tearDown(() { | 333 unittest.tearDown(() { |
| 330 _currentSchedule = null; | 334 _currentSchedule = null; |
| 331 _setUpFn = null; | 335 _setUpFn = null; |
| 332 }); | 336 }); |
| 333 } else { | 337 } else { |
| 334 unittest.setUp(() { | 338 unittest.setUp(() { |
| 335 if (currentSchedule == null) { | 339 if (_setUpFn != null) { |
| 336 throw new StateError('No schedule allocated.'); | |
| 337 } else if (_setUpFn != null) { | |
| 338 var parentFn = _setUpFn; | 340 var parentFn = _setUpFn; |
| 339 _setUpFn = () { parentFn(); setUpFn(); }; | 341 _setUpFn = () { parentFn(); setUpFn(); }; |
| 340 } else { | 342 } else { |
| 341 _setUpFn = setUpFn; | 343 _setUpFn = setUpFn; |
| 342 } | 344 } |
| 343 }); | 345 }); |
| 344 } | 346 } |
| 345 } | 347 } |
| 346 | 348 |
| 347 /// Ensures that the global configuration for `scheduled_test` has been | 349 /// Ensures that the global configuration for `scheduled_test` has been |
| (...skipping 20 matching lines...) Expand all Loading... |
| 368 /// [description] provides an optional description of the future, which is | 370 /// [description] provides an optional description of the future, which is |
| 369 /// used when generating error messages. | 371 /// used when generating error messages. |
| 370 Future wrapFuture(Future future, [String description]) { | 372 Future wrapFuture(Future future, [String description]) { |
| 371 if (currentSchedule == null) { | 373 if (currentSchedule == null) { |
| 372 throw new StateError("Unexpected call to wrapFuture with no current " | 374 throw new StateError("Unexpected call to wrapFuture with no current " |
| 373 "schedule."); | 375 "schedule."); |
| 374 } | 376 } |
| 375 | 377 |
| 376 return currentSchedule.wrapFuture(future, description); | 378 return currentSchedule.wrapFuture(future, description); |
| 377 } | 379 } |
| OLD | NEW |