diff --git a/README.md b/README.md index 563be2dc..b7f51ed4 100644 --- a/README.md +++ b/README.md @@ -395,6 +395,11 @@ object. +* Individual test files can be executed by appending their path to the end of the command. + +``` +ddev test path/to/test_name path/to/another/test_name +``` ## CLI Usage diff --git a/lib/src/tasks/test/cli.dart b/lib/src/tasks/test/cli.dart index 79d9d5ef..8f7bbf9f 100644 --- a/lib/src/tasks/test/cli.dart +++ b/lib/src/tasks/test/cli.dart @@ -15,6 +15,7 @@ library dart_dev.src.tasks.test.cli; import 'dart:async'; +import 'dart:io'; import 'package:args/args.dart'; @@ -28,8 +29,7 @@ import 'package:dart_dev/src/tasks/test/config.dart'; class TestCli extends TaskCli { final ArgParser argParser = new ArgParser() - ..addFlag('unit', - defaultsTo: defaultUnit, help: 'Includes the unit test suite.') + ..addFlag('unit', defaultsTo: null, help: 'Includes the unit test suite.') ..addFlag('integration', defaultsTo: defaultIntegration, help: 'Includes the integration test suite.') @@ -45,6 +45,32 @@ class TestCli extends TaskCli { final String command = 'test'; + bool hasRestParams(ArgResults parsedArgs) { + return parsedArgs.rest.length > 0; + } + + Future addToTestsFromRest(List tests, List rest) async { + int restLength = rest.length; + int individualTests = 0; + //verify this is a test-file and it exists. + for (var i = 0; i < restLength; i++) { + String filePath = rest[i]; + await new File(filePath).exists().then((bool exists) { + if (exists) { + individualTests++; + tests.add(filePath); + } else { + print("Ignoring unknown argument"); + } + }); + } + return individualTests; + } + + bool isExplicitlyFalse(bool value) { + return value != null && value == false; + } + Future run(ArgResults parsedArgs) async { if (!platform_util .hasImmediateDependency('test')) return new CliResult.fail( @@ -52,6 +78,9 @@ class TestCli extends TaskCli { bool unit = parsedArgs['unit']; bool integration = parsedArgs['integration']; + List tests = []; + int individualTests = 0; + var concurrency = TaskCli.valueOf('concurrency', parsedArgs, config.test.concurrency); if (concurrency is String) { @@ -60,18 +89,24 @@ class TestCli extends TaskCli { List platforms = TaskCli.valueOf('platform', parsedArgs, config.test.platforms); - if (!unit && !integration) { + if (hasRestParams(parsedArgs)) { + individualTests = await addToTestsFromRest(tests, parsedArgs.rest); + } + + if (isExplicitlyFalse(unit) && !integration && individualTests == 0) { return new CliResult.fail( 'No tests were selected. Include at least one of --unit or --integration.'); + } else { + if (individualTests == 0) unit = true; } - List tests = []; if (unit) { tests.addAll(config.test.unitTests); } if (integration) { tests.addAll(config.test.integrationTests); } + if (tests.isEmpty) { if (unit && config.test.unitTests.isEmpty) { return new CliResult.fail( diff --git a/test/integration/test_test.dart b/test/integration/test_test.dart index 6cc5b219..4cb9f340 100644 --- a/test/integration/test_test.dart +++ b/test/integration/test_test.dart @@ -26,12 +26,24 @@ const String projectWithFailingTests = 'test/fixtures/test/failing'; const String projectWithPassingTests = 'test/fixtures/test/passing'; Future runTests(String projectPath, - {bool unit: true, bool integration: false}) async { + {bool unit: true, bool integration: false, List files}) async { await Process.run('pub', ['get'], workingDirectory: projectPath); List args = ['run', 'dart_dev', 'test']; - args.add(unit ? '--unit' : '--no-unit'); - args.add(integration ? '--integration' : '--no-integration'); + if (unit != null) args.add(unit ? '--unit' : '--no-unit'); + if (integration != null) args + .add(integration ? '--integration' : '--no-integration'); + int i; + + if (files != null) { + int filesLength = files.length; + if (filesLength > 0) { + for (i = 0; i < filesLength; i++) { + args.add(files[i]); + } + } + } + TaskProcess process = new TaskProcess('pub', args, workingDirectory: projectPath); @@ -55,6 +67,22 @@ void main() { isFalse); }); + test('should run individual unit test', () async { + expect( + await runTests(projectWithPassingTests, files: + ['test/fixtures/test/passing/test/passing_unit_test.dart']), + isTrue); + }); + + test('should run individual unit tests', () async { + expect( + await runTests(projectWithPassingTests, files: [ + 'test/fixtures/test/passing/test/passing_unit_test.dart', + 'test/fixtures/test/passing/test/passing_unit_integration.dart' + ]), + isTrue); + }); + test('should run unit tests', () async { expect( await runTests(projectWithPassingTests, @@ -62,6 +90,13 @@ void main() { isTrue); }); + test('should run unit tests by default', () async { + expect( + await runTests(projectWithPassingTests, + unit: null, integration: null), + isTrue); + }); + test('should run integration tests', () async { expect( await runTests(projectWithPassingTests,