Support the latest version of the test package. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1160453004
diff --git a/CHANGELOG.md b/CHANGELOG.md index ce13637..d097f00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md
@@ -1,3 +1,17 @@ +# 0.2.0 + +* Full compatibility with `test` `0.12.0`. + +* Tests are no longer run in their own isolates. Instead, each test's + environment is isolated manually using the `test` package's infrastructure. + +* `initMetatest` is no longer necessary and has been removed. + +* `metaSetUp` has been removed; the `test` package's `setUp` may be used + instead. + +* `expectTestResults` has been removed. + # 0.1.1 * Changed maximum version of `unittest` to support development.
diff --git a/lib/metatest.dart b/lib/metatest.dart index d037a0e..61a4ef0 100644 --- a/lib/metatest.dart +++ b/lib/metatest.dart
@@ -12,257 +12,79 @@ import 'dart:async'; import 'dart:isolate'; -import 'package:unittest/unittest.dart'; +// TODO(nweiz): Stop importing from src when dart-lang/test#48 is fixed. +import 'package:test/src/backend/declarer.dart'; +import 'package:test/src/backend/state.dart'; +import 'package:test/src/backend/suite.dart'; +import 'package:test/src/runner/engine.dart'; +import 'package:test/test.dart'; -import 'src/utils.dart'; - -/// Whether or not we're running in a child isolate that's supposed to run a -/// test. -bool _inChildIsolate; - -/// The port with which the child isolate should communicate with the parent -/// isolate. +/// Declares a test with the given [description] and [body]. /// -/// `null` in the parent isolate. -SendPort _replyTo; - -/// The only value of the configuration used in metatest. -final _metaConfiguration = new _MetaConfiguration(); - -/// The function holding the tests to be run. -Function _testBody; - -/// The description of the test to run in the child isolate. -/// -/// `null` in the parent isolate. -String _testToRun; - -/// Stores the optional timeout used to override the default unittest timeout. -Duration _timeoutOverride; - -/// Runs [setUpFn] before every metatest. -/// -/// Note that [setUpFn] will be overwritten if the test itself calls [setUp]. -void metaSetUp(void setUpFn()) { - if (_inChildIsolate) setUp(setUpFn); -} - -/// Runs a set of tests defined in `body` and checks the result by comparing -/// with values in `expectedResults`. -/// -/// [expectedResults] is a list which should have a [Map] value for each test -/// that is run. Each [Map] key corresponds to values from a completed test -/// case: "description", "message", "result", and "stackTrace". -/// -/// The value of "result" can be one of: 'pass', 'fail', or 'error'. -/// -/// The value for "stackTrace" is the [String] 'null' if the property is `null` -/// on the source test case. Otherwise, it is the output of `toString`. The -/// format is not guaranteed. -/// -/// Here's an example of a `expectedResults` value for two tests, where the -/// where the first fails and the second passes. -/// -/// ```dart -/// [{ -/// 'description': 'test', -/// 'message': 'Caught error!', -/// 'result': 'fail', -/// }, { -/// 'description': 'follow up', -/// 'result': 'pass', -/// }] -/// ``` -void expectTestResults(String description, void body(), - List<Map> expectedResults) { - _setUpTest(description, body, (resultsMap) { - var list = resultsMap['results']; - expect(list, hasLength(expectedResults.length), - reason: 'The number of tests run does not match the number of expected' - ' results.'); - - for (var i = 0; i < list.length; i++) { - var expectedMap = expectedResults[i]; - var map = list[i]; - - expectedMap.forEach((key, value) { - expect(map, containsPair(key, value), reason: 'A test did not match the' - ' expected value for "$key" at index $i.'); - }); - } - }); -} - -/// Declares a test with the given [description] and [body]. [body] corresponds -/// to the `main` method of a test file, and will be run in an isolate. By -/// default, this expects that all tests defined in [body] pass, but if -/// [passing] is passed, only tests listed there are expected to pass. +/// [body] corresponds to the `main` method of a test file. By default, this +/// expects that all tests defined in [body] pass, but if [passing] is passed, +/// only tests listed there are expected to pass. void expectTestsPass(String description, void body(), {List<String> passing}) { - _setUpTest(description, body, (results) { - if (_hasError(results)) { - fail('Expected all tests to pass, but got error(s):\n' - '${_summarizeTests(results)}'); - } else if (passing == null) { - if (results['failed'] != 0) { + _setUpTest(description, body, (liveTests) { + if (passing == null) { + if (liveTests.any( + (liveTest) => liveTest.state.result != Result.success)) { fail('Expected all tests to pass, but some failed:\n' - '${_summarizeTests(results)}'); + '${_summarizeTests(liveTests)}'); } - } else { - var shouldPass = new Set.from(passing); - var didPass = new Set.from(results['results'] - .where((t) => t['result'] == 'pass') - .map((t) => t['description'])); + return; + } - if (!shouldPass.containsAll(didPass) || - !didPass.containsAll(shouldPass)) { - String stringify(Set<String> tests) => - '{${tests.map((t) => '"$t"').join(', ')}}'; + var shouldPass = new Set.from(passing); + var didPass = new Set.from(liveTests + .where((liveTest) => liveTest.state.result == Result.success) + .map((liveTest) => liveTest.test.name)); - fail('Expected exactly ${stringify(shouldPass)} to pass, but ' - '${stringify(didPass)} passed.\n' - '${_summarizeTests(results)}'); - } + if (!shouldPass.containsAll(didPass) || + !didPass.containsAll(shouldPass)) { + stringify(tests) => '{${tests.map((t) => '"$t"').join(', ')}}'; + + fail('Expected exactly ${stringify(shouldPass)} to pass, but ' + '${stringify(didPass)} passed.\n' + '${_summarizeTests(liveTests)}'); } }); } -/// Declares a test with the given [description] and [body]. [body] corresponds -/// to the `main` method of a test file, and will be run in an isolate. Expects -/// all tests defined by [body] to fail. -void expectTestsFail(String description, void body()) { - _setUpTest(description, body, (results) { - if (_hasError(results)) { - throw 'Expected all tests to fail, but got error(s):\n' - '${_summarizeTests(results)}'; - } else if (results['passed'] != 0) { - throw 'Expected all tests to fail, but some passed:\n' - '${_summarizeTests(results)}'; - } - }); +/// Asserts that all tests defined by [body] fail. +/// +/// [body] corresponds to the `main` method of a test file. +void expectTestsFail(String description, body()) { + expectTestsPass(description, body, passing: []); } /// Sets up a test with the given [description] and [body]. After the test runs, /// calls [validate] with the result map. -void _setUpTest(String description, void body(), void validate(Map map)) { - if (_inChildIsolate) { - _ensureInitialized(); - if (_testToRun == description) body(); - } else { - test(description, () { - return _runInIsolate(description).then(validate); - }); - } +void _setUpTest(String description, void body(), + void validate(List<LiveTest> liveTests)) { + test(description, () async { + var declarer = new Declarer(); + runZoned(body, zoneValues: {#test.declarer: declarer}); + + var engine = new Engine([new Suite(declarer.tests)]); + for (var test in engine.liveTests) { + test.onPrint.listen(print); + } + await engine.run(); + + validate(engine.liveTests); + }); } -/// Initialize metatest. -/// -/// [message] should be the second argument to [main]. It's used to determine -/// whether this test is in the parent isolate or a child isolate. -/// -/// [timeout], when specified, overrides the default timeout for unittest. -void initMetatest(message, {Duration timeout}) { - _timeoutOverride = timeout; - if (message == null) { - _inChildIsolate = false; - } else { - _testToRun = message['testToRun']; - _replyTo = message['replyTo']; - _inChildIsolate = true; - } -} - -// TODO(kevmoo) We need to capture the main method to allow running in an -// isolate. There is no mechanism to capture the current executing URI between -// browser and vm. Issue 1145 and/or Issue 8440 -void initTests(void testBody(message)) { - _testBody = testBody; - _testBody(null); -} - -/// Runs the test described by [description] in its own isolate. -/// -/// Returns a map describing the results of that test run. -Future<Map> _runInIsolate(String description) { - if (_testBody == null) { - throw new StateError('initTests was not called.'); - } - - var replyPort = new ReceivePort(); - return Isolate.spawn(_testBody, { - 'testToRun': description, - 'replyTo': replyPort.sendPort - }).then((_) => replyPort.first); -} - -/// Returns whether [results] (a test result map) describes a test run in which -/// an error occurred. -bool _hasError(Map results) { - return results['errors'] > 0 || results['uncaughtError'] != null || - (results['passed'] == 0 && results['failed'] == 0); -} - -/// Returns a string description of the test run descibed by [results]. -String _summarizeTests(Map results) { +/// Returns a string description of the test run descibed by [liveTests]. +String _summarizeTests(List<LiveTest> liveTests) { var buffer = new StringBuffer(); - for (var t in results["results"]) { - buffer.writeln("${t['result'].toUpperCase()}: ${t['description']}"); - if (t['message'] != '') buffer.writeln("${_indent(t['message'])}"); - if (t['stackTrace'] != null && t['stackTrace'] != '') { - buffer.writeln("${_indent(t['stackTrace'])}"); + for (var liveTest in liveTests) { + buffer.writeln("${liveTest.state.result}: ${liveTest.test.name}"); + for (var error in liveTest.errors) { + buffer.writeln(error.error); + if (error.stackTrace != null) buffer.writeln(error.stackTrace); } } - - buffer.writeln(); - - if (results['passed'] == 0 && results['failed'] == 0 && - results['errors'] == 0 && results['uncaughtError'] == null) { - buffer.write('No tests found.'); - // This is considered a failure too. - } else if (results['failed'] == 0 && results['errors'] == 0 && - results['uncaughtError'] == null) { - buffer.write('All ${results['passed']} tests passed.'); - } else { - if (results['uncaughtError'] != null) { - buffer.write('Top-level uncaught error: ${results['uncaughtError']}'); - } - buffer.write('${results['passed']} PASSED, ${results['failed']} FAILED, ' - '${results['errors']} ERRORS'); - } - return prefixLines(buffer.toString()); -} - -/// Indents each line of [str] by two spaces. -String _indent(String str) { - return str.replaceAll(new RegExp("^", multiLine: true), " "); -} - -/// Ensure that the metatest configuration is loaded. -void _ensureInitialized() { - unittestConfiguration = _metaConfiguration; - if (_timeoutOverride != null) { - unittestConfiguration.timeout = _timeoutOverride; - } -} - -/// Special test configuration for use within the child isolates. This hides all -/// output and reports data back to the parent isolate. -class _MetaConfiguration extends Configuration { - - _MetaConfiguration() : super.blank(); - - void onSummary(int passed, int failed, int errors, List<TestCase> results, - String uncaughtError) { - _replyTo.send({ - "passed": passed, - "failed": failed, - "errors": errors, - "uncaughtError": uncaughtError, - "results": results.map((testCase) => { - "description": testCase.description, - "message": testCase.message, - "result": testCase.result, - "stackTrace": testCase.stackTrace.toString() - }).toList() - }); - } + return buffer.toString(); }
diff --git a/lib/src/utils.dart b/lib/src/utils.dart deleted file mode 100644 index 542f289..0000000 --- a/lib/src/utils.dart +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library metatest.utils; - -/// Prepends each line in [text] with [prefix]. If [firstPrefix] is passed, the -/// first line is prefixed with that instead. -String prefixLines(String text, {String prefix: '| ', String firstPrefix}) { - var lines = text.split('\n'); - if (firstPrefix == null) { - return lines.map((line) => '$prefix$line').join('\n'); - } - - var firstLine = "$firstPrefix${lines.first}"; - lines = lines.skip(1).map((line) => '$prefix$line').toList(); - lines.insert(0, firstLine); - return lines.join('\n'); -}
diff --git a/pubspec.yaml b/pubspec.yaml index d6d35a0..b5da3bc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml
@@ -1,9 +1,9 @@ name: metatest -version: 0.1.2-dev +version: 0.2.0 author: Dart Team <misc@dartlang.org> description: A package for testing Dart test frameworks. homepage: https://github.com/dart-lang/metatest environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.8.0 <2.0.0' dependencies: - unittest: '>=0.11.0 <0.13.0' + test: '>=0.12.0 <0.13.0'