Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: lib/unittest/unittest.dart

Issue 10335007: First pass at a generic reusable command line option parser. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to review. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** 5 /**
6 * A library for writing dart unit tests. 6 * A library for writing dart unit tests.
7 * 7 *
8 * ##Concepts## 8 * ##Concepts##
9 * 9 *
10 * * Tests: Tests are specified via the top-level function [test], they can be 10 * * Tests: Tests are specified via the top-level function [test], they can be
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 */ 165 */
166 final _UNCAUGHT_ERROR = 3; 166 final _UNCAUGHT_ERROR = 3;
167 167
168 int _state = _UNINITIALIZED; 168 int _state = _UNINITIALIZED;
169 String _uncaughtErrorMessage = null; 169 String _uncaughtErrorMessage = null;
170 170
171 final _PASS = 'pass'; 171 final _PASS = 'pass';
172 final _FAIL = 'fail'; 172 final _FAIL = 'fail';
173 final _ERROR = 'error'; 173 final _ERROR = 'error';
174 174
175 /** If set, then all other test cases will be ignored. */
176 TestCase _soloTest;
177
175 /** Creates an expectation for the given value. */ 178 /** Creates an expectation for the given value. */
176 Expectation expect(value) => new Expectation(value); 179 Expectation expect(value) => new Expectation(value);
177 180
178 /** Evaluates the given function and validates that it throws an exception. */ 181 /**
179 void expectThrow(function) { 182 * Evaluates the [function] and validates that it throws an exception. If
183 * [callback] is provided, then it will be invoked with the thrown exception.
184 * The callback may do any validation it wants. In addition, if it returns
185 * `false`, that also indicates an expectation failure.
186 */
187 void expectThrow(function, [bool callback(exception)]) {
180 bool threw = false; 188 bool threw = false;
181 try { 189 try {
182 function(); 190 function();
183 } catch (var e) { 191 } catch (var e) {
184 threw = true; 192 threw = true;
193
194 // Also let the callback look at it.
195 if (callback != null) {
196 var result = callback(e);
197
198 // If the callback explicitly returned false, treat that like an
199 // expectation too. (If it returns null, though, don't.)
200 if (result == false) {
201 _fail('Exception:\n$e\ndid not match expectation.');
202 }
203 }
185 } 204 }
186 Expect.equals(true, threw, 'Expected exception but none was thrown.'); 205
206 if (threw != true) _fail('An expected exception was not thrown.');
187 } 207 }
188 208
189 /** 209 /**
190 * Creates a new test case with the given description and body. The 210 * Creates a new test case with the given description and body. The
191 * description will include the descriptions of any surrounding group() 211 * description will include the descriptions of any surrounding group()
192 * calls. 212 * calls.
193 */ 213 */
194 void test(String spec, TestFunction body) { 214 void test(String spec, TestFunction body) {
195 ensureInitialized(); 215 ensureInitialized();
196 216
(...skipping 12 matching lines...) Expand all
209 final testCase = new TestCase( 229 final testCase = new TestCase(
210 _tests.length + 1, _fullSpec(spec), body, callbacks); 230 _tests.length + 1, _fullSpec(spec), body, callbacks);
211 _tests.add(testCase); 231 _tests.add(testCase);
212 232
213 if (callbacks < 1) { 233 if (callbacks < 1) {
214 testCase.error( 234 testCase.error(
215 'Async tests must wait for at least one callback ', ''); 235 'Async tests must wait for at least one callback ', '');
216 } 236 }
217 } 237 }
218 238
239 /**
240 * Creates a new test case with the given description and body. The
241 * description will include the descriptions of any surrounding group()
242 * calls.
243 *
244 * "solo_" means that this will be the only test that is run. All other tests
245 * will be skipped. This is a convenience function to let you quickly isolate
246 * a single test by adding "solo_" before it to temporarily disable all other
247 * tests.
248 */
249 void solo_test(String spec, TestFunction body) {
nweiz 2012/05/03 21:07:08 Incorrect indentation.
Bob Nystrom 2012/05/03 22:31:20 Done.
250 // TODO(rnystrom): Support multiple solos. If more than one test is solo-ed,
251 // all of the solo-ed tests and none of the non-solo-ed ones should run.
Siggi Cherem (dart-lang) 2012/05/03 00:32:41 this sort of contradicts the term 'solo_' :)
252 if (_soloTest != null) {
253 throw new Exception('Only one test can be soloed right now.');
254 }
255
256 ensureInitialized();
257
258 _soloTest = new TestCase(_tests.length + 1, _fullSpec(spec), body, 0);
259 _tests.add(_soloTest);
260 }
261
219 /** Sentinel value for [_SpreadArgsHelper]. */ 262 /** Sentinel value for [_SpreadArgsHelper]. */
220 class _Sentinel { 263 class _Sentinel {
221 const _Sentinel(); 264 const _Sentinel();
222 } 265 }
223 266
224 // TODO(sigmund): make a singleton const field when frog supports passing those 267 // TODO(sigmund): make a singleton const field when frog supports passing those
225 // as default values to named arguments. 268 // as default values to named arguments.
226 final _sentinel = const _Sentinel(); 269 final _sentinel = const _Sentinel();
227 270
228 /** Simulates spread arguments using named arguments. */ 271 /** Simulates spread arguments using named arguments. */
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 final port = new ReceivePort(); 444 final port = new ReceivePort();
402 port.receive((msg, reply) { 445 port.receive((msg, reply) {
403 callback(); 446 callback();
404 port.close(); 447 port.close();
405 }); 448 });
406 port.toSendPort().send(null, null); 449 port.toSendPort().send(null, null);
407 } 450 }
408 451
409 /** Runs all queued tests, one at a time. */ 452 /** Runs all queued tests, one at a time. */
410 _runTests() { 453 _runTests() {
454 // If we are soloing a test, remove all the others.
455 if (_soloTest != null) {
456 _tests = _tests.filter((t) => t == _soloTest);
457 }
458
411 _config.onStart(); 459 _config.onStart();
412 460
413 _defer(() { 461 _defer(() {
414 assert (_currentTest == 0); 462 assert (_currentTest == 0);
415 _testRunner(); 463 _testRunner();
416 }); 464 });
417 } 465 }
418 466
419 /** 467 /**
420 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update 468 * Run [tryBody] guarded in a try-catch block. If an exception is thrown, update
421 * the [_currentTest] status accordingly. 469 * the [_currentTest] status accordingly.
422 */ 470 */
423 _guard(tryBody, [finallyBody]) { 471 _guard(tryBody, [finallyBody]) {
424 try { 472 try {
425 return tryBody(); 473 return tryBody();
426 } catch (ExpectException e, var trace) { 474 } catch (ExpectException e, var trace) {
427 if (_state != _UNCAUGHT_ERROR) { 475 if (_state != _UNCAUGHT_ERROR) {
428 _tests[_currentTest].fail(e.message, 476 _tests[_currentTest].fail(e.message,
429 trace == null ? '' : trace.toString()); 477 trace == null ? '' : trace.toString());
430 } 478 }
431 } catch (var e, var trace) { 479 } catch (var e, var trace) {
432 if (_state != _UNCAUGHT_ERROR) { 480 if (_state == _RUNNING_TEST) {
481 // If a random exception is thrown from within a test, we consider that
482 // a test failure too. A test case implicitly has an expectation that it
483 // will run to completion without an uncaught exception being thrown.
484 _tests[_currentTest].fail('Caught $e',
485 trace == null ? '' : trace.toString());
486 } else if (_state != _UNCAUGHT_ERROR) {
433 _tests[_currentTest].error('Caught $e', 487 _tests[_currentTest].error('Caught $e',
434 trace == null ? '' : trace.toString()); 488 trace == null ? '' : trace.toString());
435 } 489 }
436 } finally { 490 } finally {
437 _state = _READY; 491 _state = _READY;
438 if (finallyBody != null) finallyBody(); 492 if (finallyBody != null) finallyBody();
439 } 493 }
440 } 494 }
441 495
442 /** 496 /**
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 540
487 _config.onDone(testsPassed_, testsFailed_, testsErrors_, _tests, 541 _config.onDone(testsPassed_, testsFailed_, testsErrors_, _tests,
488 _uncaughtErrorMessage); 542 _uncaughtErrorMessage);
489 } 543 }
490 544
491 String _fullSpec(String spec) { 545 String _fullSpec(String spec) {
492 if (spec === null) return '$_currentGroup'; 546 if (spec === null) return '$_currentGroup';
493 return _currentGroup != '' ? '$_currentGroup $spec' : spec; 547 return _currentGroup != '' ? '$_currentGroup $spec' : spec;
494 } 548 }
495 549
550 void _fail(String message) {
551 throw new ExpectException(message);
552 }
553
496 /** 554 /**
497 * Lazily initializes the test library if not already initialized. 555 * Lazily initializes the test library if not already initialized.
498 */ 556 */
499 ensureInitialized() { 557 ensureInitialized() {
500 if (_state != _UNINITIALIZED) return; 558 if (_state != _UNINITIALIZED) return;
501 559
502 _tests = <TestCase>[]; 560 _tests = <TestCase>[];
503 _currentGroup = ''; 561 _currentGroup = '';
504 _state = _READY; 562 _state = _READY;
505 _testRunner = _nextBatch; 563 _testRunner = _nextBatch;
506 564
507 if (_config == null) { 565 if (_config == null) {
508 _config = new Configuration(); 566 _config = new Configuration();
509 } 567 }
510 _config.onInit(); 568 _config.onInit();
511 569
512 // Immediately queue the suite up. It will run after a timeout (i.e. after 570 // Immediately queue the suite up. It will run after a timeout (i.e. after
513 // main() has returned). 571 // main() has returned).
514 _defer(_runTests); 572 _defer(_runTests);
515 } 573 }
516 574
517 /** Signature for a test function. */ 575 /** Signature for a test function. */
518 typedef void TestFunction(); 576 typedef void TestFunction();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698