| // 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(1); |
| }); |
| }); |
| |
| 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(1); |
| }); |
| |
| 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(1); |
| }); |
| |
| 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(() 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')); |