Commit c7e00449 authored by Adam Barth's avatar Adam Barth

Make it possible to run tests outside the Flutter repo

This patch still requires a locally built engine. I'll remove the need for a
locally built engine in a future patch.

Fixes #278
parent 0e290946
...@@ -83,15 +83,11 @@ class Artifact { ...@@ -83,15 +83,11 @@ class Artifact {
return null; return null;
} }
String getUrl(String revision) {
return _getCloudStorageBaseUrl(
platform: platform,
revision: revision
) + fileName;
}
// Whether the artifact needs to be marked as executable on disk. // Whether the artifact needs to be marked as executable on disk.
bool get executable => type == ArtifactType.snapshot; bool get executable {
return type == ArtifactType.snapshot ||
(type == ArtifactType.shell && targetPlatform == TargetPlatform.linux);
}
} }
class ArtifactStore { class ArtifactStore {
...@@ -102,6 +98,12 @@ class ArtifactStore { ...@@ -102,6 +98,12 @@ class ArtifactStore {
type: ArtifactType.shell, type: ArtifactType.shell,
targetPlatform: TargetPlatform.android targetPlatform: TargetPlatform.android
), ),
const Artifact._(
name: 'Sky Shell',
fileName: 'sky_shell',
type: ArtifactType.shell,
targetPlatform: TargetPlatform.linux
),
const Artifact._( const Artifact._(
name: 'Sky Snapshot', name: 'Sky Snapshot',
fileName: 'sky_snapshot', fileName: 'sky_snapshot',
......
...@@ -19,6 +19,12 @@ abstract class FlutterCommand extends Command { ...@@ -19,6 +19,12 @@ abstract class FlutterCommand extends Command {
/// Whether this command needs to be run from the root of a project. /// Whether this command needs to be run from the root of a project.
bool get requiresProjectRoot => true; bool get requiresProjectRoot => true;
String get projectRootValidationErrorMessage {
return 'Error: No pubspec.yaml file found.\n'
'This command should be run from the root of your Flutter project. Do not run\n'
'this command from the root of your git clone of Flutter.';
}
List<BuildConfiguration> get buildConfigurations => runner.buildConfigurations; List<BuildConfiguration> get buildConfigurations => runner.buildConfigurations;
Future downloadApplicationPackages() async { Future downloadApplicationPackages() async {
...@@ -48,19 +54,19 @@ abstract class FlutterCommand extends Command { ...@@ -48,19 +54,19 @@ abstract class FlutterCommand extends Command {
} }
Future<int> run() async { Future<int> run() async {
if (requiresProjectRoot) { if (requiresProjectRoot && !validateProjectRoot())
if (!FileSystemEntity.isFileSync('pubspec.yaml')) { return 1;
stderr.writeln('Error: No pubspec.yaml file found. '
'This command should be run from the root of your Flutter project. '
'Do not run this command from the root of your git clone '
'of Flutter.');
return 1;
}
}
return await runInProject(); return await runInProject();
} }
bool validateProjectRoot() {
if (!FileSystemEntity.isFileSync('pubspec.yaml')) {
stderr.writeln(projectRootValidationErrorMessage);
return false;
}
return true;
}
Future<int> runInProject(); Future<int> runInProject();
ApplicationPackageStore applicationPackages; ApplicationPackageStore applicationPackages;
......
...@@ -22,6 +22,12 @@ class TestCommand extends FlutterCommand { ...@@ -22,6 +22,12 @@ class TestCommand extends FlutterCommand {
bool get requiresProjectRoot => false; bool get requiresProjectRoot => false;
String get projectRootValidationErrorMessage {
return 'Error: No pubspec.yaml file found.\n'
'If you wish to run the tests in the flutter repo, pass --flutter-repo before\n'
'any test paths. Otherwise, run this command from the root of your project.';
}
String getShellPath(TargetPlatform platform, String buildPath) { String getShellPath(TargetPlatform platform, String buildPath) {
switch (platform) { switch (platform) {
case TargetPlatform.linux: case TargetPlatform.linux:
...@@ -33,34 +39,59 @@ class TestCommand extends FlutterCommand { ...@@ -33,34 +39,59 @@ class TestCommand extends FlutterCommand {
} }
} }
TestCommand() {
argParser.addFlag('flutter-repo', help: 'Run tests from the Flutter repository instead of the current directory.', defaultsTo: false);
}
Iterable<String> _findTests(Directory directory) {
return directory.listSync(recursive: true, followLinks: false)
.where((FileSystemEntity entity) => entity.path.endsWith('_test.dart') && FileSystemEntity.isFileSync(entity.path))
.map((FileSystemEntity entity) => path.absolute(entity.path));
}
Directory get _flutterUnitTestDir {
return new Directory(path.join(ArtifactStore.flutterRoot, 'packages', 'unit', 'test'));
}
Future<int> _runTests(List<String> testArgs, Directory testDirectory) async {
Directory currentDirectory = Directory.current;
try {
Directory.current = testDirectory;
return await executable.main(testArgs);
} finally {
Directory.current = currentDirectory;
}
}
@override @override
Future<int> runInProject() async { Future<int> runInProject() async {
List<String> testArgs = argResults.rest.toList(); List<String> testArgs = argResults.rest.map((String testPath) => path.absolute(testPath)).toList();
Directory flutterDir = new Directory(path.join(ArtifactStore.flutterRoot, 'packages/unit')); // see https://github.com/flutter/flutter/issues/50
Directory testDir = new Directory(path.join(flutterDir.path, 'test')); final bool runFlutterTests = argResults['flutter-repo'];
if (testArgs.isEmpty) { if (!runFlutterTests && !validateProjectRoot())
testArgs.addAll(testDir.listSync(recursive: true, followLinks: false) return 1;
.where((FileSystemEntity entity) => entity.path.endsWith('_test.dart') && FileSystemEntity.isFileSync(entity.path))
.map((FileSystemEntity entity) => path.absolute(entity.path))); Directory testDir = runFlutterTests ? _flutterUnitTestDir : Directory.current;
}
if (testArgs.isEmpty)
testArgs.addAll(_findTests(testDir));
testArgs.insert(0, '--'); testArgs.insert(0, '--');
if (Platform.environment['TERM'] == 'dumb') if (Platform.environment['TERM'] == 'dumb')
testArgs.insert(0, '--no-color'); testArgs.insert(0, '--no-color');
List<BuildConfiguration> configs = buildConfigurations; List<BuildConfiguration> configs = buildConfigurations;
bool foundOne = false; bool foundOne = false;
String currentDirectory = Directory.current.path;
Directory.current = flutterDir.path;
loader.installHook(); loader.installHook();
for (BuildConfiguration config in configs) { for (BuildConfiguration config in configs) {
if (!config.testable) if (!config.testable)
continue; continue;
foundOne = true; foundOne = true;
loader.shellPath = path.join(currentDirectory, getShellPath(config.targetPlatform, config.buildDir)); loader.shellPath = path.join(Directory.current.path, getShellPath(config.targetPlatform, config.buildDir));
if (!FileSystemEntity.isFileSync(loader.shellPath)) { if (!FileSystemEntity.isFileSync(loader.shellPath)) {
_logging.severe('Cannot find Flutter shell at ${loader.shellPath}'); _logging.severe('Cannot find Flutter shell at ${loader.shellPath}');
return 1; return 1;
} }
await executable.main(testArgs); await _runTests(testArgs, testDir);
if (exitCode != 0) if (exitCode != 0)
return exitCode; return exitCode;
} }
...@@ -71,4 +102,4 @@ class TestCommand extends FlutterCommand { ...@@ -71,4 +102,4 @@ class TestCommand extends FlutterCommand {
return 0; return 0;
} }
} }
\ No newline at end of file
...@@ -5,7 +5,7 @@ set -ex ...@@ -5,7 +5,7 @@ set -ex
./bin/flutter analyze --flutter-repo --no-current-directory --no-current-package --congratulate ./bin/flutter analyze --flutter-repo --no-current-directory --no-current-package --congratulate
# flutter package tests # flutter package tests
./bin/flutter test --engine-src-path bin/cache/travis ./bin/flutter test --flutter-repo --engine-src-path bin/cache/travis
(cd packages/cassowary; pub run test -j1) (cd packages/cassowary; pub run test -j1)
# (cd packages/flutter_sprites; ) # No tests to run. # (cd packages/flutter_sprites; ) # No tests to run.
......
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