blob: 381536724c53ad75c2eb169c5178d50df49a0e90 [file] [log] [blame]
// Copyright (c) 2015, 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.
import 'dart:async';
import 'package:test/src/backend/declarer.dart';
import 'package:test/src/backend/invoker.dart';
import 'package:test/src/backend/suite.dart';
import 'package:test/src/frontend/timeout.dart';
import 'package:test/test.dart';
import '../utils.dart';
Declarer _declarer;
Suite _suite;
void main() {
setUp(() {
_declarer = new Declarer();
_suite = new Suite([]);
});
group(".test()", () {
test("declares a test with a description and body", () async {
var bodyRun = false;
_declarer.test("description", () {
bodyRun = true;
});
expect(_declarer.tests, hasLength(1));
expect(_declarer.tests.single.name, equals("description"));
await _runTest(0);
expect(bodyRun, isTrue);
});
test("declares multiple tests", () {
_declarer.test("description 1", () {});
_declarer.test("description 2", () {});
_declarer.test("description 3", () {});
expect(_declarer.tests, hasLength(3));
expect(_declarer.tests[0].name, equals("description 1"));
expect(_declarer.tests[1].name, equals("description 2"));
expect(_declarer.tests[2].name, equals("description 3"));
});
});
group(".setUp()", () {
test("is run before all tests", () async {
var setUpRun = false;
_declarer.setUp(() => setUpRun = true);
_declarer.test("description 1", expectAsync(() {
expect(setUpRun, isTrue);
setUpRun = false;
}, max: 1));
_declarer.test("description 2", expectAsync(() {
expect(setUpRun, isTrue);
setUpRun = false;
}, max: 1));
await _runTest(0);
await _runTest(1);
});
test("can return a Future", () {
var setUpRun = false;
_declarer.setUp(() {
return new Future(() => setUpRun = true);
});
_declarer.test("description", expectAsync(() {
expect(setUpRun, isTrue);
}, max: 1));
return _runTest(0);
});
test("can't be called multiple times", () {
_declarer.setUp(() {});
expect(() => _declarer.setUp(() {}), throwsStateError);
});
});
group(".tearDown()", () {
test("is run after all tests", () async {
var tearDownRun;
_declarer.setUp(() => tearDownRun = false);
_declarer.tearDown(() => tearDownRun = true);
_declarer.test("description 1", expectAsync(() {
expect(tearDownRun, isFalse);
}, max: 1));
_declarer.test("description 2", expectAsync(() {
expect(tearDownRun, isFalse);
}, max: 1));
await _runTest(0);
expect(tearDownRun, isTrue);
await _runTest(1);
expect(tearDownRun, isTrue);
});
test("is run after an out-of-band failure", () async {
var tearDownRun;
_declarer.setUp(() => tearDownRun = false);
_declarer.tearDown(() => tearDownRun = true);
_declarer.test("description 1", expectAsync(() {
Invoker.current.addOutstandingCallback();
new Future(() => throw new TestFailure("oh no"));
}, max: 1));
await _runTest(0, shouldFail: true);
expect(tearDownRun, isTrue);
});
test("can return a Future", () async {
var tearDownRun = false;
_declarer.tearDown(() {
return new Future(() => tearDownRun = true);
});
_declarer.test("description", expectAsync(() {
expect(tearDownRun, isFalse);
}, max: 1));
await _runTest(0);
expect(tearDownRun, isTrue);
});
test("isn't run until there are no outstanding callbacks", () async {
var outstandingCallbackRemoved = false;
var outstandingCallbackRemovedBeforeTeardown = false;
_declarer.tearDown(() {
outstandingCallbackRemovedBeforeTeardown = outstandingCallbackRemoved;
});
_declarer.test("description", () {
Invoker.current.addOutstandingCallback();
pumpEventQueue().then((_) {
outstandingCallbackRemoved = true;
Invoker.current.removeOutstandingCallback();
});
});
await _runTest(0);
expect(outstandingCallbackRemovedBeforeTeardown, isTrue);
});
test("doesn't complete until there are no outstanding callbacks", () async {
var outstandingCallbackRemoved = false;
_declarer.tearDown(() {
Invoker.current.addOutstandingCallback();
pumpEventQueue().then((_) {
outstandingCallbackRemoved = true;
Invoker.current.removeOutstandingCallback();
});
});
_declarer.test("description", () {});
await _runTest(0);
expect(outstandingCallbackRemoved, isTrue);
});
test("can't be called multiple times", () {
_declarer.tearDown(() {});
expect(() => _declarer.tearDown(() {}), throwsStateError);
});
});
group("in a group,", () {
test("tests inherit the group's description", () {
_declarer.group("group", () {
_declarer.test("description", () {});
});
expect(_declarer.tests, hasLength(1));
expect(_declarer.tests.single.name, "group description");
});
test("a test's timeout factor is applied to the group's", () {
_declarer.group("group", () {
_declarer.test("test", () {},
timeout: new Timeout.factor(3));
}, timeout: new Timeout.factor(2));
expect(_declarer.tests, hasLength(1));
expect(_declarer.tests.single.metadata.timeout.scaleFactor, equals(6));
});
test("a test's timeout factor is applied to the group's duration", () {
_declarer.group("group", () {
_declarer.test("test", () {},
timeout: new Timeout.factor(2));
}, timeout: new Timeout(new Duration(seconds: 10)));
expect(_declarer.tests, hasLength(1));
expect(_declarer.tests.single.metadata.timeout.duration,
equals(new Duration(seconds: 20)));
});
test("a test's timeout duration is applied over the group's", () {
_declarer.group("group", () {
_declarer.test("test", () {},
timeout: new Timeout(new Duration(seconds: 15)));
}, timeout: new Timeout(new Duration(seconds: 10)));
expect(_declarer.tests, hasLength(1));
expect(_declarer.tests.single.metadata.timeout.duration,
equals(new Duration(seconds: 15)));
});
group(".setUp()", () {
test("is scoped to the group", () async {
var setUpRun = false;
_declarer.group("group", () {
_declarer.setUp(() => setUpRun = true);
_declarer.test("description 1", expectAsync(() {
expect(setUpRun, isTrue);
setUpRun = false;
}, max: 1));
});
_declarer.test("description 2", expectAsync(() {
expect(setUpRun, isFalse);
setUpRun = false;
}, max: 1));
await _runTest(0);
await _runTest(1);
});
test("runs from the outside in", () {
var outerSetUpRun = false;
var middleSetUpRun = false;
var innerSetUpRun = false;
_declarer.setUp(expectAsync(() {
expect(middleSetUpRun, isFalse);
expect(innerSetUpRun, isFalse);
outerSetUpRun = true;
}, max: 1));
_declarer.group("middle", () {
_declarer.setUp(expectAsync(() {
expect(outerSetUpRun, isTrue);
expect(innerSetUpRun, isFalse);
middleSetUpRun = true;
}, max: 1));
_declarer.group("inner", () {
_declarer.setUp(expectAsync(() {
expect(outerSetUpRun, isTrue);
expect(middleSetUpRun, isTrue);
innerSetUpRun = true;
}, max: 1));
_declarer.test("description", expectAsync(() {
expect(outerSetUpRun, isTrue);
expect(middleSetUpRun, isTrue);
expect(innerSetUpRun, isTrue);
}, max: 1));
});
});
return _runTest(0);
});
test("handles Futures when chained", () {
var outerSetUpRun = false;
var innerSetUpRun = false;
_declarer.setUp(expectAsync(() {
expect(innerSetUpRun, isFalse);
return new Future(() => outerSetUpRun = true);
}, max: 1));
_declarer.group("inner", () {
_declarer.setUp(expectAsync(() {
expect(outerSetUpRun, isTrue);
return new Future(() => innerSetUpRun = true);
}, max: 1));
_declarer.test("description", expectAsync(() {
expect(outerSetUpRun, isTrue);
expect(innerSetUpRun, isTrue);
}, max: 1));
});
return _runTest(0);
});
test("can't be called multiple times", () {
_declarer.group("group", () {
_declarer.setUp(() {});
expect(() => _declarer.setUp(() {}), throwsStateError);
});
});
});
group(".tearDown()", () {
test("is scoped to the group", () async {
var tearDownRun;
_declarer.setUp(() => tearDownRun = false);
_declarer.group("group", () {
_declarer.tearDown(() => tearDownRun = true);
_declarer.test("description 1", expectAsync(() {
expect(tearDownRun, isFalse);
}, max: 1));
});
_declarer.test("description 2", expectAsync(() {
expect(tearDownRun, isFalse);
}, max: 1));
await _runTest(0);
expect(tearDownRun, isTrue);
await _runTest(1);
expect(tearDownRun, isFalse);
});
test("runs from the inside out", () async {
var innerTearDownRun = false;
var middleTearDownRun = false;
var outerTearDownRun = false;
_declarer.tearDown(expectAsync(() {
expect(innerTearDownRun, isTrue);
expect(middleTearDownRun, isTrue);
outerTearDownRun = true;
}, max: 1));
_declarer.group("middle", () {
_declarer.tearDown(expectAsync(() {
expect(innerTearDownRun, isTrue);
expect(outerTearDownRun, isFalse);
middleTearDownRun = true;
}, max: 1));
_declarer.group("inner", () {
_declarer.tearDown(expectAsync(() {
expect(outerTearDownRun, isFalse);
expect(middleTearDownRun, isFalse);
innerTearDownRun = true;
}, max: 1));
_declarer.test("description", expectAsync(() {
expect(outerTearDownRun, isFalse);
expect(middleTearDownRun, isFalse);
expect(innerTearDownRun, isFalse);
}, max: 1));
});
});
await _runTest(0);
expect(innerTearDownRun, isTrue);
expect(middleTearDownRun, isTrue);
expect(outerTearDownRun, isTrue);
});
test("handles Futures when chained", () async {
var outerTearDownRun = false;
var innerTearDownRun = false;
_declarer.tearDown(expectAsync(() {
expect(innerTearDownRun, isTrue);
return new Future(() => outerTearDownRun = true);
}, max: 1));
_declarer.group("inner", () {
_declarer.tearDown(expectAsync(() {
expect(outerTearDownRun, isFalse);
return new Future(() => innerTearDownRun = true);
}, max: 1));
_declarer.test("description", expectAsync(() {
expect(outerTearDownRun, isFalse);
expect(innerTearDownRun, isFalse);
}, max: 1));
});
await _runTest(0);
expect(innerTearDownRun, isTrue);
expect(outerTearDownRun, isTrue);
});
test("runs outer callbacks even when inner ones fail", () async {
var outerTearDownRun = false;
_declarer.tearDown(() {
return new Future(() => outerTearDownRun = true);
});
_declarer.group("inner", () {
_declarer.tearDown(() {
throw 'inner error';
});
_declarer.test("description", expectAsync(() {
expect(outerTearDownRun, isFalse);
}, max: 1));
});
await _runTest(0, shouldFail: true);
expect(outerTearDownRun, isTrue);
});
test("can't be called multiple times", () {
_declarer.group("group", () {
_declarer.tearDown(() {});
expect(() => _declarer.tearDown(() {}), throwsStateError);
});
});
});
});
}
/// Runs the test at [index] defined on [_declarer].
///
/// This automatically sets up an `onError` listener to ensure that the test
/// doesn't throw any invisible exceptions.
Future _runTest(int index, {bool shouldFail: false}) {
var liveTest = _declarer.tests[index].load(_suite);
liveTest.onError.listen(shouldFail
? expectAsync((_) {})
: expectAsync((_) {},
count: 0, reason: "No errors expected for test #$index."));
return liveTest.run();
}