Commit 6841ab22 authored by Brian Slesinsky's avatar Brian Slesinsky Committed by GitHub

Add --name and --plain-name to 'flutter test' (#11020)

This adds a way to run only a subset of the tests.
(The new flags do the same thing as 'pub run test'.)
parent 0a915d6f
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:test/test.dart';
void main() {
test('included', () {
expect(2 + 2, 4);
});
test('excluded', () {
throw "this test should have been filtered out";
});
}
......@@ -22,6 +22,18 @@ import '../test/watcher.dart';
class TestCommand extends FlutterCommand {
TestCommand({ bool verboseHelp: false }) {
usesPubOption();
argParser.addOption('name',
help: 'A regular expression matching substrings of the names of tests to run.',
valueHelp: 'regexp',
allowMultiple: true,
splitCommas: false,
);
argParser.addOption('plain-name',
help: 'A plain-text substring of the names of tests to run.',
valueHelp: 'substring',
allowMultiple: true,
splitCommas: false,
);
argParser.addFlag('start-paused',
defaultsTo: false,
negatable: false,
......@@ -141,6 +153,8 @@ class TestCommand extends FlutterCommand {
}
commandValidator();
final List<String> names = argResults['name'];
final List<String> plainNames = argResults['plain-name'];
Iterable<String> files = argResults.rest.map<String>((String testPath) => fs.path.absolute(testPath)).toList();
......@@ -189,6 +203,8 @@ class TestCommand extends FlutterCommand {
final int result = await runTests(files,
workDir: workDir,
names: names,
plainNames: plainNames,
watcher: watcher,
enableObservatory: collector != null || startPaused,
startPaused: startPaused,
......
......@@ -21,6 +21,8 @@ import 'watcher.dart';
Future<int> runTests(
List<String> testFiles, {
Directory workDir,
List<String> names: const <String>[],
List<String> plainNames: const <String>[],
bool enableObservatory: false,
bool startPaused: false,
bool ipv6: false,
......@@ -41,6 +43,14 @@ Future<int> runTests(
testArgs.addAll(<String>['-r', 'json']);
}
for (String name in names) {
testArgs..add("--name")..add(name);
}
for (String plainName in plainNames) {
testArgs..add("--plain-name")..add(plainName);
}
testArgs.add('--');
testArgs.addAll(testFiles);
......
......@@ -18,63 +18,63 @@ import '../src/context.dart';
Future<Null> _testExclusionLock;
void main() {
group('test', () {
group('flutter test should', () {
final String automatedTestsDirectory = fs.path.join('..', '..', 'dev', 'automated_tests');
final String flutterTestDirectory = fs.path.join(automatedTestsDirectory, 'flutter_test');
testUsingContext('Exception handling in test harness', () async {
testUsingContext('report nice errors for exceptions thrown within testWidgets()', () async {
Cache.flutterRoot = '../..';
return _testFile('exception_handling', automatedTestsDirectory, flutterTestDirectory);
});
testUsingContext('TestAsyncUtils guarded function test', () async {
testUsingContext('report a nice error when a guarded function was called without await', () async {
Cache.flutterRoot = '../..';
return _testFile('test_async_utils_guarded', automatedTestsDirectory, flutterTestDirectory);
});
testUsingContext('TestAsyncUtils unguarded function test', () async {
testUsingContext('report a nice error when an async function was called without await', () async {
Cache.flutterRoot = '../..';
return _testFile('test_async_utils_unguarded', automatedTestsDirectory, flutterTestDirectory);
});
testUsingContext('Missing flutter_test dependency', () async {
testUsingContext('report a nice error when a pubspec.yaml is missing a flutter_test dependency', () async {
final String missingDependencyTests = fs.path.join('..', '..', 'dev', 'missing_dependency_tests');
Cache.flutterRoot = '../..';
return _testFile('trivial', missingDependencyTests, missingDependencyTests);
});
testUsingContext('run a test when its name matches a regexp', () async {
Cache.flutterRoot = '../..';
final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
extraArgs: const <String>["--name", "inc.*de"]);
if (!result.stdout.contains("+1: All tests passed"))
fail("unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n");
expect(result.exitCode, 0);
});
testUsingContext('run a test when its name contains a string', () async {
Cache.flutterRoot = '../..';
final ProcessResult result = await _runFlutterTest('filtering', automatedTestsDirectory, flutterTestDirectory,
extraArgs: const <String>["--plain-name", "include"]);
if (!result.stdout.contains("+1: All tests passed"))
fail("unexpected output from test:\n\n${result.stdout}\n-- end stdout --\n\n");
expect(result.exitCode, 0);
});
}, skip: io.Platform.isWindows); // TODO(goderbauer): enable when sky_shell is available
}
Future<Null> _testFile(String testName, String workingDirectory, String testDirectory) async {
final String fullTestName = fs.path.join(testDirectory, '${testName}_test.dart');
final File testFile = fs.file(fullTestName);
expect(testFile.existsSync(), true);
final String fullTestExpectation = fs.path.join(testDirectory, '${testName}_expectation.txt');
final File expectationFile = fs.file(fullTestExpectation);
expect(expectationFile.existsSync(), true);
if (!expectationFile.existsSync())
fail("missing expectation file: $expectationFile");
while (_testExclusionLock != null)
await _testExclusionLock;
ProcessResult exec;
final Completer<Null> testExclusionCompleter = new Completer<Null>();
_testExclusionLock = testExclusionCompleter.future;
try {
exec = await Process.run(
fs.path.join(dartSdkPath, 'bin', 'dart'),
<String>[
fs.path.absolute(fs.path.join('bin', 'flutter_tools.dart')),
'test',
'--no-color',
fullTestName,
],
workingDirectory: workingDirectory,
);
} finally {
_testExclusionLock = null;
testExclusionCompleter.complete();
}
final ProcessResult exec = await _runFlutterTest(testName, workingDirectory, testDirectory);
expect(exec.exitCode, isNonZero);
final List<String> output = exec.stdout.split('\n');
......@@ -115,3 +115,34 @@ Future<Null> _testFile(String testName, String workingDirectory, String testDire
if (!haveSeenStdErrMarker)
expect(exec.stderr, '');
}
Future<ProcessResult> _runFlutterTest(String testName, String workingDirectory, String testDirectory,
{List<String> extraArgs = const <String>[]}) async {
final String testFilePath = fs.path.join(testDirectory, '${testName}_test.dart');
final File testFile = fs.file(testFilePath);
if (!testFile.existsSync())
fail("missing test file: $testFile");
final List<String> args = <String>[
fs.path.absolute(fs.path.join('bin', 'flutter_tools.dart')),
'test',
'--no-color'
]..addAll(extraArgs)..add(testFilePath);
while (_testExclusionLock != null)
await _testExclusionLock;
final Completer<Null> testExclusionCompleter = new Completer<Null>();
_testExclusionLock = testExclusionCompleter.future;
try {
return await Process.run(
fs.path.join(dartSdkPath, 'bin', 'dart'),
args,
workingDirectory: workingDirectory,
);
} finally {
_testExclusionLock = null;
testExclusionCompleter.complete();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment