blob: 7fb2cee85b706882fe37c5c7bba93cd5ec880ecf [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() {
setUpAll(precompileTestExecutable);
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(79);
});
});
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(79);
});
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(79);
});
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,chrome', '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: 'chrome');
});
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([
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) 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.
mayEmitMultiple(isNot(anyOf([contains(' was used in'), isEmpty]))),
isEmpty,
]);
/// Returns a [StreamMatcher] that matches the lines of [string] in order.
StreamMatcher lines(String string) => emitsInOrder(string.split('\n'));