blob: 992c589091a93c1193a4d2087581ccf790e7716d [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.
@TestOn("vm")
import 'package:test_descriptor/test_descriptor.dart' as d;
import 'package:test/test.dart';
import '../io.dart';
void main() {
setUp(() async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
test("no tags", () {});
test("a", () {}, tags: "a");
test("b", () {}, tags: "b");
test("bc", () {}, tags: ["b", "c"]);
}
""").create();
});
group("--tags", () {
test("runs all tests when no tags are specified", () async {
var test = await runTest(["test.dart"]);
expect(test.stdout, tagWarnings(['a', 'b', 'c']));
expect(test.stdout, emitsThrough(contains(": no tags")));
expect(test.stdout, emitsThrough(contains(": a")));
expect(test.stdout, emitsThrough(contains(": b")));
expect(test.stdout, emitsThrough(contains(": bc")));
expect(test.stdout, emitsThrough(contains("+4: All tests passed!")));
await test.shouldExit(0);
});
test("runs a test with only a specified tag", () async {
var test = await runTest(["--tags=a", "test.dart"]);
expect(test.stdout, tagWarnings(['b', 'c']));
expect(test.stdout, emitsThrough(contains(": a")));
expect(test.stdout, emitsThrough(contains("+1: All tests passed!")));
await test.shouldExit(0);
});
test("runs a test with a specified tag among others", () async {
var test = await runTest(["--tags=c", "test.dart"]);
expect(test.stdout, tagWarnings(['a', 'b']));
expect(test.stdout, emitsThrough(contains(": bc")));
expect(test.stdout, emitsThrough(contains("+1: All tests passed!")));
await test.shouldExit(0);
});
test("with multiple tags, runs only tests matching all of them", () async {
var test = await runTest(["--tags=b,c", "test.dart"]);
expect(test.stdout, tagWarnings(['a']));
expect(test.stdout, emitsThrough(contains(": bc")));
expect(test.stdout, emitsThrough(contains("+1: All tests passed!")));
await test.shouldExit(0);
});
test("supports boolean selector syntax", () async {
var test = await runTest(["--tags=b || c", "test.dart"]);
expect(test.stdout, tagWarnings(['a']));
expect(test.stdout, emitsThrough(contains(": b")));
expect(test.stdout, emitsThrough(contains(": bc")));
expect(test.stdout, emitsThrough(contains("+2: All tests passed!")));
await test.shouldExit(0);
});
test("prints no warnings when all tags are specified", () async {
var test = await runTest(["--tags=a,b,c", "test.dart"]);
expect(test.stdout, emitsThrough(contains("No tests ran.")));
await test.shouldExit(0);
});
});
group("--exclude-tags", () {
test("dosn't run a test with only an excluded tag", () async {
var test = await runTest(["--exclude-tags=a", "test.dart"]);
expect(test.stdout, tagWarnings(['b', 'c']));
expect(test.stdout, emitsThrough(contains(": no tags")));
expect(test.stdout, emitsThrough(contains(": b")));
expect(test.stdout, emitsThrough(contains(": bc")));
expect(test.stdout, emitsThrough(contains("+3: All tests passed!")));
await test.shouldExit(0);
});
test("doesn't run a test with an exluded tag among others", () async {
var test = await runTest(["--exclude-tags=c", "test.dart"]);
expect(test.stdout, tagWarnings(['a', 'b']));
expect(test.stdout, emitsThrough(contains(": no tags")));
expect(test.stdout, emitsThrough(contains(": a")));
expect(test.stdout, emitsThrough(contains(": b")));
expect(test.stdout, emitsThrough(contains("+3: All tests passed!")));
await test.shouldExit(0);
});
test("dosn't load a suite with an excluded tag", () async {
await d.file("test.dart", """
@Tags(const ["a"])
import 'package:test/test.dart';
void main() {
throw "error";
}
""").create();
var test = await runTest(["--exclude-tags=a", "test.dart"]);
expect(test.stdout, emits("No tests ran."));
await test.shouldExit(0);
});
test("allows unused tags", () async {
var test = await runTest(["--exclude-tags=b,z", "test.dart"]);
expect(test.stdout, tagWarnings(['a', 'c']));
expect(test.stdout, emitsThrough(contains(": no tags")));
expect(test.stdout, emitsThrough(contains(": a")));
expect(test.stdout, emitsThrough(contains("+2: All tests passed!")));
await test.shouldExit(0);
});
test("supports boolean selector syntax", () async {
var test = await runTest(["--exclude-tags=b && c", "test.dart"]);
expect(test.stdout, tagWarnings(['a']));
expect(test.stdout, emitsThrough(contains(": no tags")));
expect(test.stdout, emitsThrough(contains(": a")));
expect(test.stdout, emitsThrough(contains(": b")));
expect(test.stdout, emitsThrough(contains("+3: All tests passed!")));
await test.shouldExit(0);
});
test("prints no warnings when all tags are specified", () async {
var test = await runTest(["--exclude-tags=a,b,c", "test.dart"]);
expect(test.stdout, emitsThrough(contains(": no tags")));
expect(test.stdout, emitsThrough(contains("+1: All tests passed!")));
await test.shouldExit(0);
});
});
group("with a tagged group", () {
setUp(() async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
group("a", () {
test("in", () {});
}, tags: "a");
test("out", () {});
}
""").create();
});
test("includes tags specified on the group", () async {
var test = await runTest(["-x", "a", "test.dart"]);
expect(test.stdout, emitsThrough(contains(": out")));
expect(test.stdout, emitsThrough(contains("+1: All tests passed!")));
await test.shouldExit(0);
});
test("excludes tags specified on the group", () async {
var test = await runTest(["-t", "a", "test.dart"]);
expect(test.stdout, emitsThrough(contains(": a in")));
expect(test.stdout, emitsThrough(contains("+1: All tests passed!")));
await test.shouldExit(0);
});
});
test('respects top-level @Tags annotations', () async {
await d.file("test.dart", """
@Tags(const ['a'])
import 'package:test/test.dart';
void main() {
test("foo", () {});
}
""").create();
var test = await runTest(["-x", "a", "test.dart"]);
expect(test.stdout, emitsThrough(contains("No tests ran")));
await test.shouldExit(0);
});
group("warning formatting", () {
test("for multiple tags", () async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
test("foo", () {}, tags: ["a", "b"]);
}
""").create();
var test = await runTest(["test.dart"]);
expect(
test.stdout,
emitsThrough(lines(
'Warning: Tags were used that weren\'t specified in dart_test.yaml.\n'
' a was used in the test "foo"\n'
' b was used in the test "foo"')));
await test.shouldExit(0);
});
test("for multiple tests", () async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
test("foo", () {}, tags: "a");
test("bar", () {}, tags: "a");
}
""").create();
var test = await runTest(["test.dart"]);
expect(
test.stdout,
emitsThrough(lines(
'Warning: A tag was used that wasn\'t specified in dart_test.yaml.\n'
' a was used in:\n'
' the test "foo"\n'
' the test "bar"')));
await test.shouldExit(0);
});
test("for groups", () async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
group("group", () {
test("foo", () {});
test("bar", () {});
}, tags: "a");
}
""").create();
var test = await runTest(["test.dart"]);
expect(
test.stdout,
emitsThrough(lines(
'Warning: A tag was used that wasn\'t specified in dart_test.yaml.\n'
' a was used in the group "group"')));
await test.shouldExit(0);
});
test("for suites", () async {
await d.file("test.dart", """
@Tags(const ["a"])
import 'package:test/test.dart';
void main() {
test("foo", () {});
test("bar", () {});
}
""").create();
var test = await runTest(["test.dart"]);
expect(
test.stdout,
emitsThrough(lines(
'Warning: A tag was used that wasn\'t specified in dart_test.yaml.\n'
' a was used in the suite itself')));
await test.shouldExit(0);
});
test("doesn't double-print a tag warning", () async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
test("foo", () {}, tags: "a");
}
""").create();
var test = await runTest(["-p", "vm,content-shell", "test.dart"]);
expect(
test.stdout,
emitsThrough(lines(
'Warning: A tag was used that wasn\'t specified in dart_test.yaml.\n'
' a was used in the test "foo"')));
expect(test.stdout, neverEmits(startsWith("Warning:")));
await test.shouldExit(0);
}, tags: "content-shell");
});
group("invalid tags", () {
test("are disallowed by test()", () async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
test("foo", () {}, tags: "a b");
}
""").create();
var test = await runTest(["test.dart"]);
expect(
test.stdout,
emitsThrough(
' Failed to load "test.dart": Invalid argument(s): Invalid tag "a '
'b". Tags must be (optionally hyphenated) Dart identifiers.'));
await test.shouldExit(1);
});
test("are disallowed by group()", () async {
await d.file("test.dart", """
import 'package:test/test.dart';
void main() {
group("group", () {
test("foo", () {});
}, tags: "a b");
}
""").create();
var test = await runTest(["test.dart"]);
expect(
test.stdout,
emitsThrough(
' Failed to load "test.dart": Invalid argument(s): Invalid tag "a '
'b". Tags must be (optionally hyphenated) Dart identifiers.'));
await test.shouldExit(1);
});
test("are disallowed by @Tags()", () async {
await d.file("test.dart", """
@Tags(const ["a b"])
import 'package:test/test.dart';
void main() {
test("foo", () {});
}
""").create();
var test = await runTest(["test.dart"]);
expect(
test.stdout,
emitsThrough(lines(' Failed to load "test.dart":\n'
' Error on line 1, column 22: Invalid tag name. Tags must be '
'(optionally hyphenated) Dart identifiers.')));
await test.shouldExit(1);
});
});
}
/// Returns a [StreamMatcher] that asserts that a test emits warnings for [tags]
/// in order.
StreamMatcher tagWarnings(List<String> tags) => emitsInOrder(() sync* {
yield emitsThrough(
"Warning: ${tags.length == 1 ? 'A tag was' : 'Tags were'} used that "
"${tags.length == 1 ? "wasn't" : "weren't"} specified in "
"dart_test.yaml.");
for (var tag in tags) {
yield emitsThrough(startsWith(" $tag was used in"));
}
// Consume until the end of the warning block, and assert that it has no
// further tags than the ones we specified.
yield mayEmitMultiple(isNot(anyOf([contains(" was used in"), isEmpty])));
yield isEmpty;
}());
/// Returns a [StreamMatcher] that matches the lines of [string] in order.
StreamMatcher lines(String string) => emitsInOrder(string.split("\n"));