allow passing file path as reference to devicelab task (#6877)
This commit is contained in:
parent
473df6d632
commit
4145f5fcfd
@ -7,13 +7,15 @@ This package contains the code for test framework and the tests. More generally
|
|||||||
the tests are referred to as "tasks" in the API, but since we primarily use it
|
the tests are referred to as "tasks" in the API, but since we primarily use it
|
||||||
for testing, this document refers to them as "tests".
|
for testing, this document refers to them as "tests".
|
||||||
|
|
||||||
If you have access to Google's internal network, you can see the continuous build results from the master branch at
|
If you have access to Google's internal network, you can see the continuous
|
||||||
<http://go/flutter-dashboard/build.html>. (There is currently no public view of this data, unfortunately.)
|
build results from the master branch at <http://go/flutter-dashboard/build.html>.
|
||||||
|
(There is currently no public view of this data, unfortunately.)
|
||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
|
|
||||||
You must set the `ANDROID_HOME` environment variable to run tests on Android. If you
|
You must set the `ANDROID_HOME` environment variable to run tests on Android. If
|
||||||
have a local build of the Flutter engine, then you have a copy of the Android SDK at `.../engine/src/third_party/android_tools/sdk`.
|
you have a local build of the Flutter engine, then you have a copy of the
|
||||||
|
Android SDK at `.../engine/src/third_party/android_tools/sdk`.
|
||||||
|
|
||||||
# Running tests locally
|
# Running tests locally
|
||||||
|
|
||||||
@ -26,10 +28,16 @@ To run a test, use option `-t` (`--task`):
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
# from the .../flutter/dev/devicelab directory
|
# from the .../flutter/dev/devicelab directory
|
||||||
dart bin/run.dart -t {NAME_OF_TEST}
|
dart bin/run.dart -t {NAME_OR_PATH_OF_TEST}
|
||||||
```
|
```
|
||||||
|
|
||||||
You can see the test names in the `manifest.yaml` file in this directory or by looking in `bin/tasks/`. Do not include the `.dart` file extension. For example, `dart bin/run.dart -t complex_layout__start_up`.
|
Where `NAME_OR_PATH_OF_TEST` can be either of:
|
||||||
|
|
||||||
|
- the _name_ of a task, which you can find in the `manifest.yaml` file in this
|
||||||
|
directory. Example: `complex_layout__start_up`.
|
||||||
|
- the path to a Dart _file_ corresponding to a task, which resides in `bin/tasks`.
|
||||||
|
Tip: most shells support path auto-completion using the Tab key. Example:
|
||||||
|
`bin/tasks/complex_layout__start_up.dart`.
|
||||||
|
|
||||||
To run multiple tests, repeat option `-t` (`--task`) multiple times:
|
To run multiple tests, repeat option `-t` (`--task`) multiple times:
|
||||||
|
|
||||||
@ -54,8 +62,8 @@ Currently there are only two stages defined, `devicelab` and `devicelab_ios`.
|
|||||||
# Reproducing broken builds locally
|
# Reproducing broken builds locally
|
||||||
|
|
||||||
If a commit caused a test to fail,
|
If a commit caused a test to fail,
|
||||||
[the dashboard](http://go/flutter-dashboard/build.html) (requires access to the Google network, sorry) might look something
|
[the dashboard](http://go/flutter-dashboard/build.html) (requires access to the
|
||||||
like this:
|
Google network, sorry) might look something like this:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -7,11 +7,14 @@ import 'dart:convert';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:args/args.dart';
|
import 'package:args/args.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
import 'package:flutter_devicelab/framework/manifest.dart';
|
import 'package:flutter_devicelab/framework/manifest.dart';
|
||||||
import 'package:flutter_devicelab/framework/runner.dart';
|
import 'package:flutter_devicelab/framework/runner.dart';
|
||||||
import 'package:flutter_devicelab/framework/utils.dart';
|
import 'package:flutter_devicelab/framework/utils.dart';
|
||||||
|
|
||||||
|
List<String> _taskNames = <String>[];
|
||||||
|
|
||||||
/// Runs tasks.
|
/// Runs tasks.
|
||||||
///
|
///
|
||||||
/// The tasks are chosen depending on the command-line options
|
/// The tasks are chosen depending on the command-line options
|
||||||
@ -28,24 +31,23 @@ Future<Null> main(List<String> rawArgs) async {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> taskNames = <String>[];
|
if (!args.wasParsed('task')) {
|
||||||
if (args.wasParsed('task')) {
|
if (args.wasParsed('stage')) {
|
||||||
taskNames.addAll(args['task']);
|
String stageName = args['stage'];
|
||||||
} else if (args.wasParsed('stage')) {
|
List<ManifestTask> tasks = loadTaskManifest().tasks;
|
||||||
String stageName = args['stage'];
|
for (ManifestTask task in tasks) {
|
||||||
List<ManifestTask> tasks = loadTaskManifest().tasks;
|
if (task.stage == stageName)
|
||||||
for (ManifestTask task in tasks) {
|
_taskNames.add(task.name);
|
||||||
if (task.stage == stageName)
|
}
|
||||||
taskNames.add(task.name);
|
} else if (args.wasParsed('all')) {
|
||||||
}
|
List<ManifestTask> tasks = loadTaskManifest().tasks;
|
||||||
} else if (args.wasParsed('all')) {
|
for (ManifestTask task in tasks) {
|
||||||
List<ManifestTask> tasks = loadTaskManifest().tasks;
|
_taskNames.add(task.name);
|
||||||
for (ManifestTask task in tasks) {
|
}
|
||||||
taskNames.add(task.name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taskNames.isEmpty) {
|
if (_taskNames.isEmpty) {
|
||||||
stderr.writeln('Failed to find tasks to run based on supplied options.');
|
stderr.writeln('Failed to find tasks to run based on supplied options.');
|
||||||
exitCode = 1;
|
exitCode = 1;
|
||||||
return null;
|
return null;
|
||||||
@ -53,7 +55,7 @@ Future<Null> main(List<String> rawArgs) async {
|
|||||||
|
|
||||||
bool silent = args['silent'];
|
bool silent = args['silent'];
|
||||||
|
|
||||||
for (String taskName in taskNames) {
|
for (String taskName in _taskNames) {
|
||||||
section('Running task "$taskName"');
|
section('Running task "$taskName"');
|
||||||
Map<String, dynamic> result = await runTask(taskName, silent: silent);
|
Map<String, dynamic> result = await runTask(taskName, silent: silent);
|
||||||
|
|
||||||
@ -73,9 +75,27 @@ final ArgParser _argParser = new ArgParser()
|
|||||||
abbr: 't',
|
abbr: 't',
|
||||||
allowMultiple: true,
|
allowMultiple: true,
|
||||||
splitCommas: true,
|
splitCommas: true,
|
||||||
help: 'Name of the task to run. This option may be repeated to '
|
help: 'Either:\n'
|
||||||
'specify multiple tasks. A task selected by name does not have to be '
|
' - the name of a task defined in manifest.yaml. Example: complex_layout__start_up.\n'
|
||||||
'defined in manifest.yaml. It only needs a Dart executable in bin/tasks.',
|
' - the path to a Dart file corresponding to a task, which resides in bin/tasks. Example: bin/tasks/complex_layout__start_up.dart.\n'
|
||||||
|
'\n'
|
||||||
|
'This option may be repeated to specify multiple tasks.',
|
||||||
|
callback: (List<String> value) {
|
||||||
|
for (String nameOrPath in value) {
|
||||||
|
List<String> fragments = path.split(nameOrPath);
|
||||||
|
bool isDartFile = fragments.last.endsWith('.dart');
|
||||||
|
|
||||||
|
if (fragments.length == 1 && !isDartFile) {
|
||||||
|
// Not a path
|
||||||
|
_taskNames.add(nameOrPath);
|
||||||
|
} else if (!isDartFile || fragments.length != 3 || !_listsEqual(<String>['bin', 'tasks'], fragments.take(2).toList())) {
|
||||||
|
// Unsupported executable location
|
||||||
|
throw new FormatException('Invalid value for option -t (--task): $nameOrPath');
|
||||||
|
} else {
|
||||||
|
_taskNames.add(path.withoutExtension(fragments.last));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
..addOption(
|
..addOption(
|
||||||
'stage',
|
'stage',
|
||||||
@ -106,3 +126,14 @@ final ArgParser _argParser = new ArgParser()
|
|||||||
negatable: true,
|
negatable: true,
|
||||||
defaultsTo: false,
|
defaultsTo: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bool _listsEqual(List<dynamic> a, List<dynamic> b) {
|
||||||
|
if (a.length != b.length) return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < a.length; i++) {
|
||||||
|
if (a[i] != b[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -21,23 +21,31 @@ void main() {
|
|||||||
return scriptProcess.exitCode;
|
return scriptProcess.exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
test('Exits with code 0 when succeeds', () async {
|
test('exits with code 0 when succeeds', () async {
|
||||||
expect(await runScript(<String>['smoke_test_success']), 0);
|
expect(await runScript(<String>['smoke_test_success']), 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Exits with code 1 when task throws', () async {
|
test('accepts file paths', () async {
|
||||||
|
expect(await runScript(<String>['bin/tasks/smoke_test_success.dart']), 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('rejects invalid file paths', () async {
|
||||||
|
expect(await runScript(<String>['lib/framework/adb.dart']), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('exits with code 1 when task throws', () async {
|
||||||
expect(await runScript(<String>['smoke_test_throws']), 1);
|
expect(await runScript(<String>['smoke_test_throws']), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Exits with code 1 when fails', () async {
|
test('exits with code 1 when fails', () async {
|
||||||
expect(await runScript(<String>['smoke_test_failure']), 1);
|
expect(await runScript(<String>['smoke_test_failure']), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Exits with code 1 when fails to connect', () async {
|
test('exits with code 1 when fails to connect', () async {
|
||||||
expect(await runScript(<String>['smoke_test_setup_failure']), 1);
|
expect(await runScript(<String>['smoke_test_setup_failure']), 1);
|
||||||
}, skip: true); // https://github.com/flutter/flutter/issues/5901
|
}, skip: true); // https://github.com/flutter/flutter/issues/5901
|
||||||
|
|
||||||
test('Exits with code 1 when results are mixed', () async {
|
test('exits with code 1 when results are mixed', () async {
|
||||||
expect(
|
expect(
|
||||||
await runScript(<String>[
|
await runScript(<String>[
|
||||||
'smoke_test_failure',
|
'smoke_test_failure',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user