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

Unified Diff: lib/unittest.dart

Issue 934413002: Replace the existing unittest APIs with the new runner infrastructure. (Closed) Base URL: git@github.com:dart-lang/unittest@master
Patch Set: Code review changes Created 5 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/test_controller.js ('k') | lib/vm_config.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/unittest.dart
diff --git a/lib/unittest.dart b/lib/unittest.dart
index d0083270f6bfff8beadd318417477e50cb3b3a2b..0e4be92da407534374dc336240fb9613cf27951b 100644
--- a/lib/unittest.dart
+++ b/lib/unittest.dart
@@ -5,14 +5,15 @@
library unittest;
import 'dart:async';
-import 'dart:collection';
+
+import 'package:path/path.dart' as p;
import 'src/configuration.dart';
-import 'src/expected_function.dart';
-import 'src/group_context.dart';
-import 'src/internal_test_case.dart';
+import 'src/declarer.dart';
+import 'src/console_reporter.dart';
+import 'src/invoker.dart';
+import 'src/suite.dart';
import 'src/test_case.dart';
-import 'src/test_environment.dart';
export 'package:matcher/matcher.dart'
hide
@@ -44,426 +45,133 @@ export 'package:matcher/matcher.dart'
export 'src/configuration.dart';
export 'src/expect.dart';
-export 'src/simple_configuration.dart';
+export 'src/expect_async.dart';
export 'src/future_matchers.dart';
export 'src/prints_matcher.dart';
+export 'src/simple_configuration.dart';
+export 'src/test_case.dart';
export 'src/throws_matcher.dart';
export 'src/throws_matchers.dart';
-export 'src/test_case.dart';
-/// The signature for a function passed to [test].
-typedef dynamic TestFunction();
+/// The global declarer.
+///
+/// This is used if a test file is run directly, rather than through the runner.
+Declarer _globalDeclarer;
+
+/// Gets the declarer for the current scope.
+///
+/// When using the runner, this returns the [Zone]-scoped declarer that's set by
+/// [VmListener]. If the test file is run directly, this returns
+/// [_globalDeclarer] (and sets it up on the first call).
+Declarer get _declarer {
+ var declarer = Zone.current[#unittest.declarer];
+ if (declarer != null) return declarer;
+ if (_globalDeclarer != null) return _globalDeclarer;
+
+ // Since there's no Zone-scoped declarer, the test file is being run directly.
+ // In order to run the tests, we set up our own Declarer via
+ // [_globalDeclarer], and schedule a microtask to run the tests once they're
+ // finished being defined.
+ _globalDeclarer = new Declarer();
+ scheduleMicrotask(() {
+ var suite = new Suite(p.prettyUri(Uri.base), _globalDeclarer.tests);
+ // TODO(nweiz): Use a reporter that doesn't import dart:io here.
+ // TODO(nweiz): Set the exit code on the VM when issue 6943 is fixed.
+ new ConsoleReporter([suite]).run();
+ });
+ return _globalDeclarer;
+}
-/// [Configuration] used by the unittest library.
-///
-/// Note that if a configuration has not been set, calling this getter will
-/// create a default configuration.
-Configuration get unittestConfiguration {
- if (config == null) environment.config = new Configuration();
- return config;
+// TODO(nweiz): This and other top-level functions should throw exceptions if
+// they're called after the declarer has finished declaring.
+void test(String description, body()) => _declarer.test(description, body);
+
+void group(String description, void body()) =>
+ _declarer.group(description, body);
+
+void setUp(callback()) => _declarer.setUp(callback);
+
+void tearDown(callback()) => _declarer.tearDown(callback);
+
+/// Handle an error that occurs outside of any test.
+void handleExternalError(error, String message, [stackTrace]) {
+ // TODO(nweiz): handle this better.
+ registerException(error, stackTrace);
}
-/// If `true`, stack traces are reformatted to be more readable.
+/// Registers an exception that was caught for the current test.
+void registerException(error, [StackTrace stackTrace]) =>
+ Invoker.current.handleError(error, stackTrace);
+
+// What follows are stubs for various top-level names supported by unittest
+// 0.11.*. These are preserved for the time being for ease of migration, but
+// should be removed before this is released as stable.
+
+@deprecated
+typedef dynamic TestFunction();
+
+@deprecated
+Configuration unittestConfiguration = new Configuration();
+
+@deprecated
bool formatStacks = true;
-/// If `true`, irrelevant frames are filtered from the stack trace.
-///
-/// This does nothing if [formatStacks] is false.
+@deprecated
bool filterStacks = true;
-/// Separator used between group names and test names.
+@deprecated
String groupSep = ' ';
-/// Sets the [Configuration] used by the unittest library.
-///
-/// Throws a [StateError] if there is an existing, incompatible value.
-void set unittestConfiguration(Configuration value) {
- if (identical(config, value)) return;
- if (config != null) {
- logMessage('Warning: The unittestConfiguration has already been set. New '
- 'unittestConfiguration ignored.');
- } else {
- environment.config = value;
- }
-}
-
-/// Logs [message] associated with the current test case.
-///
-/// Tests should use this instead of [print].
-void logMessage(String message) =>
- config.onLogMessage(currentTestCase, message);
+@deprecated
+void logMessage(String message) => print(message);
-/// The test cases that have been defined so far.
-List<TestCase> get testCases =>
- new UnmodifiableListView<TestCase>(environment.testCases);
+@deprecated
+final testCases = [];
-/// The interval (in milliseconds) after which a non-microtask asynchronous
-/// delay will be scheduled between tests.
-///
-/// This is used to avoid starving the DOM or other non-microtask events.
+@deprecated
const int BREATH_INTERVAL = 200;
-/// The [TestCase] currently being executed.
-TestCase get currentTestCase => (environment.currentTestCaseIndex >= 0 &&
- environment.currentTestCaseIndex < testCases.length)
- ? testCases[environment.currentTestCaseIndex]
- : null;
+@deprecated
+TestCase get currentTestCase => null;
-/// The same as [currentTestCase], but typed as an [InternalTestCase].
-InternalTestCase get _currentTestCase => currentTestCase as InternalTestCase;
-
-/// The result string for a passing test case.
+@deprecated
const PASS = 'pass';
-/// The result string for a failing test case.
+@deprecated
const FAIL = 'fail';
-/// The result string for an test case with an error.
+@deprecated
const ERROR = 'error';
-/// Creates a new test case with the given description and body.
-///
-/// The description will be added to the descriptions of any surrounding
-/// [group]s.
-void test(String description, TestFunction body) {
- _requireNotRunning();
- ensureInitialized();
-
- if (environment.soloTestSeen && environment.soloNestingLevel == 0) return;
- var testCase = new InternalTestCase(
- testCases.length + 1, _fullDescription(description), body);
- environment.testCases.add(testCase);
-}
-
-/// Returns [description] with all of its group prefixes prepended.
-String _fullDescription(String description) {
- var group = environment.currentContext.fullName;
- if (description == null) return group;
- return group != '' ? '$group$groupSep$description' : description;
-}
-
-/// A convenience function for skipping a test.
+@deprecated
void skip_test(String spec, TestFunction body) {}
-/// Creates a new test case with the given description and body.
-///
-/// If [solo_test] is used instead of [test], then all non-solo tests will be
-/// disabled. Note that if [solo_group] is used as well, all tests in the group
-/// will be enabled, regardless of whether they use [test] or [solo_test], or
-/// whether they are in a nested [group] versus [solo_group]. Put another way,
-/// if there are any calls to [solo_test] or [solo_group] in a test file, all
-/// tests that are not inside a [solo_group] will be disabled unless they are
-/// [solo_test]s.
-void solo_test(String spec, TestFunction body) {
- _requireNotRunning();
- ensureInitialized();
- if (!environment.soloTestSeen) {
- environment.soloTestSeen = true;
- // This is the first solo-ed test. Discard all tests up to now.
- environment.testCases.clear();
- }
- environment.soloNestingLevel++;
- try {
- test(spec, body);
- } finally {
- environment.soloNestingLevel--;
- }
-}
+@deprecated
+void solo_test(String spec, TestFunction body) => test(spec, body);
-/// Indicate that [callback] is expected to be called [count] number of times
-/// (by default 1).
-///
-/// The unittest framework will wait for the callback to run the [count] times
-/// before it considers the current test to be complete. Using [expectAsync]
-/// will also ensure that errors that occur within [callback] are tracked and
-/// reported. [callback] may take up to six optional or required positional
-/// arguments; named arguments are not supported.
-///
-/// [max] can be used to specify an upper bound on the number of calls; if this
-/// is exceeded the test will fail. If [max] is `0` (the default), the callback
-/// is expected to be called exactly [count] times. If [max] is `-1`, the
-/// callback is allowed to be called any number of times greater than [count].
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-Function expectAsync(Function callback,
- {int count: 1, int max: 0, String id, String reason}) =>
- new ExpectedFunction(callback, count, max, id: id, reason: reason).func;
-
-/// Indicate that [callback] is expected to be called until [isDone] returns
-/// true.
-///
-/// [isDone] is called after each time the function is run. Only when it returns
-/// true will the callback be considered complete. Using [expectAsyncUntil] will
-/// also ensure that errors that occur within [callback] are tracked and
-/// reported. [callback] may take up to six optional or required positional
-/// arguments; named arguments are not supported.
-///
-/// Both [id] and [reason] are optional and provide extra information about the
-/// callback when debugging. [id] should be the name of the callback, while
-/// [reason] should be the reason the callback is expected to be called.
-Function expectAsyncUntil(Function callback, bool isDone(),
- {String id, String reason}) => new ExpectedFunction(callback, 0, -1,
- id: id, reason: reason, isDone: isDone).func;
-
-/// Creates a group of tests.
-///
-/// A group's description is included in the descriptions of any tests or
-/// sub-groups it contains. [setUp] and [tearDown] are also scoped to the
-/// containing group.
-void group(String description, void body()) {
- ensureInitialized();
- _requireNotRunning();
- environment.currentContext =
- new GroupContext(environment.currentContext, description);
- try {
- body();
- } catch (e, trace) {
- var stack = (trace == null) ? '' : ': ${trace.toString()}';
- environment.uncaughtErrorMessage = "${e.toString()}$stack";
- } finally {
- // Now that the group is over, restore the previous one.
- environment.currentContext = environment.currentContext.parent;
- }
-}
-
-/// A convenience function for skipping a group of tests.
+@deprecated
void skip_group(String description, void body()) {}
-/// Creates a group of tests.
-///
-/// If [solo_group] is used instead of [group], then all tests not declared with
-/// [solo_test] or in a [solo_group] will be disabled. Note that all tests in a
-/// [solo_group] will be run, regardless of whether they're declared with [test]
-/// or [solo_test].
-///
-/// [skip_test] and [skip_group] take precedence over [solo_group].
-void solo_group(String description, void body()) {
- _requireNotRunning();
- ensureInitialized();
- if (!environment.soloTestSeen) {
- environment.soloTestSeen = true;
- // This is the first solo-ed group. Discard all tests up to now.
- environment.testCases.clear();
- }
- ++environment.soloNestingLevel;
- try {
- group(description, body);
- } finally {
- --environment.soloNestingLevel;
- }
-}
+@deprecated
+void solo_group(String description, void body()) => group(description, body);
-/// Registers a function to be run before tests.
-///
-/// This function will be called before each test is run. [callback] may be
-/// asynchronous; if so, it must return a [Future].
-///
-/// If this is called within a test group, it applies only to tests in that
-/// group. [callback] will be run after any set-up callbacks in parent groups or
-/// at the top level.
-void setUp(Function callback) {
- _requireNotRunning();
- environment.currentContext.testSetUp = callback;
-}
+@deprecated
+void filterTests(testFilter) {}
-/// Registers a function to be run after tests.
-///
-/// This function will be called after each test is run. [callback] may be
-/// asynchronous; if so, it must return a [Future].
-///
-/// If this is called within a test group, it applies only to tests in that
-/// group. [callback] will be run before any tear-down callbacks in parent groups or
-/// at the top level.
-void tearDown(Function callback) {
- _requireNotRunning();
- environment.currentContext.testTearDown = callback;
-}
+@deprecated
+void runTests() {}
-/// Advance to the next test case.
-void _nextTestCase() {
- environment.currentTestCaseIndex++;
- _runTest();
-}
+@deprecated
+void ensureInitialized() {}
-/// Handle an error that occurs outside of any test.
-void handleExternalError(e, String message, [stackTrace]) {
- var msg = '$message\nCaught $e';
-
- if (currentTestCase != null) {
- _currentTestCase.error(msg, stackTrace);
- } else {
- environment.uncaughtErrorMessage = "$msg: $stackTrace";
- }
-}
-
-/// Remove any tests that match [testFilter].
-///
-/// [testFilter] can be a predicate function, a [RegExp], or a [String]. If it's
-/// a function, it's called with each [TestCase]. If it's a [String], it's
-/// parsed as a [RegExp] and matched against each [TestCase.description].
-///
-/// This is different from enabling or disabling tests in that it removes the
-/// tests completely.
-void filterTests(testFilter) {
- var filterFunction;
- if (testFilter is String) {
- var re = new RegExp(testFilter);
- filterFunction = (t) => re.hasMatch(t.description);
- } else if (testFilter is RegExp) {
- filterFunction = (t) => testFilter.hasMatch(t.description);
- } else if (testFilter is Function) {
- filterFunction = testFilter;
- }
- environment.testCases.retainWhere(filterFunction);
-}
+@deprecated
+void setSoloTest(int id) {}
-/// Runs all queued tests, one at a time.
-void runTests() {
- _requireNotRunning();
- _ensureInitialized(false);
- environment.currentTestCaseIndex = 0;
- config.onStart();
- _runTest();
-}
+@deprecated
+void enableTest(int id) {}
-/// Registers an exception that was caught for the current test.
-void registerException(error, [StackTrace stackTrace]) =>
- _currentTestCase.registerException(error, stackTrace);
-
-/// Runs the next test.
-void _runTest() {
- if (environment.currentTestCaseIndex >= testCases.length) {
- assert(environment.currentTestCaseIndex == testCases.length);
- _completeTests();
- return;
- }
-
- var testCase = _currentTestCase;
- var f = runZoned(testCase.run, onError: (error, stack) {
- // TODO(kevmoo) Do a better job of flagging these are async errors.
- // https://code.google.com/p/dart/issues/detail?id=16530
- testCase.registerException(error, stack);
- });
+@deprecated
+void disableTest(int id) {}
- var timer;
- var timeout = unittestConfiguration.timeout;
- if (timeout != null) {
- try {
- timer = new Timer(timeout, () {
- testCase.error("Test timed out after ${timeout.inSeconds} seconds.");
- _nextTestCase();
- });
- } on UnsupportedError catch (e) {
- if (e.message != "Timer greater than 0.") rethrow;
- // Support running on d8 and jsshell which don't support timers.
- }
- }
-
- f.whenComplete(() {
- if (timer != null) timer.cancel();
- var now = new DateTime.now().millisecondsSinceEpoch;
- if (now - environment.lastBreath >= BREATH_INTERVAL) {
- environment.lastBreath = now;
- Timer.run(_nextTestCase);
- } else {
- scheduleMicrotask(_nextTestCase); // Schedule the next test.
- }
- });
-}
-
-/// Notify the configuration that the testing has finished.
-void _completeTests() {
- if (!environment.initialized) return;
-
- var passed = 0;
- var failed = 0;
- var errors = 0;
- for (var testCase in testCases) {
- switch (testCase.result) {
- case PASS:
- passed++;
- break;
- case FAIL:
- failed++;
- break;
- case ERROR:
- errors++;
- break;
- }
- }
-
- config.onSummary(
- passed, failed, errors, testCases, environment.uncaughtErrorMessage);
- config.onDone(passed > 0 &&
- failed == 0 &&
- errors == 0 &&
- environment.uncaughtErrorMessage == null);
- environment.initialized = false;
- environment.currentTestCaseIndex = -1;
-}
-
-/// Initializes the test environment if it hasn't already been initialized.
-void ensureInitialized() {
- _ensureInitialized(true);
-}
-
-/// Initializes the test environment.
-///
-/// If [configAutoStart] is `true`, schedule a microtask to run the tests. This
-/// microtask is expected to run after all the tests are defined.
-void _ensureInitialized(bool configAutoStart) {
- if (environment.initialized) return;
-
- environment.initialized = true;
-
- environment.uncaughtErrorMessage = null;
-
- unittestConfiguration.onInit();
-
- // Immediately queue the suite up. It will run after a timeout (i.e. after
- // main() has returned).
- if (configAutoStart && config.autoStart) scheduleMicrotask(runTests);
-}
-
-/// Remove all tests other than the one identified by [id].
-void setSoloTest(int id) =>
- environment.testCases.retainWhere((t) => t.id == id);
-
-/// Enable the test identified by [id].
-void enableTest(int id) => _setTestEnabledState(id, enable: true);
-
-/// Disable the test by [id].
-void disableTest(int id) => _setTestEnabledState(id, enable: false);
-
-/// Enable or disable the test identified by [id].
-void _setTestEnabledState(int id, {bool enable: true}) {
- // Try fast path first.
- if (testCases.length > id && testCases[id].id == id) {
- environment.testCases[id].enabled = enable;
- } else {
- for (var i = 0; i < testCases.length; i++) {
- if (testCases[i].id != id) continue;
- environment.testCases[i].enabled = enable;
- break;
- }
- }
-}
-
-/// Throws a [StateError] if tests are running.
-void _requireNotRunning() {
- if (environment.currentTestCaseIndex == -1) return;
- throw new StateError('Not allowed when tests are running.');
-}
-
-/// Creates a test environment running in its own zone scope.
-///
-/// This allows for multiple invocations of the unittest library in the same
-/// application instance. This is useful when, for example, creating a test
-/// runner application which needs to create a new pristine test environment on
-/// each invocation to run a given set of tests.
-withTestEnvironment(callback()) {
- return runZoned(callback,
- zoneValues: {#unittest.environment: new TestEnvironment()});
-}
+@deprecated
+withTestEnvironment(callback()) => callback();
« no previous file with comments | « lib/test_controller.js ('k') | lib/vm_config.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698