diff --git a/README.md b/README.md index c0ee576e..825889cd 100644 --- a/README.md +++ b/README.md @@ -746,6 +746,74 @@ or Windows: ./gradlew.bat build ``` +# Testing + +To run the tests, you need the following tools installed: + * Unity (with iOS and Android modules installed) + +You can run the tests by running the following from your shell +(Linux / OSX): + +``` +./gradlew test +``` + +or Windows: + +``` +./gradlew.bat test +``` + +The following properties can be set to narrow down the tests to run or change +the test run behavior. + +* `INTERACTIVE_MODE_TESTS_ENABLED` - Default to `1`. Set to `1` to enable + interactive mode tests, which requires GPU on the machine. Otherwise, only run + tests in the batch mode. +* `INCLUDE_TEST_TYPES` - Default to empty string, which means to include every + type of the test. To narrow down the types of test to run, set this properties + with a list of case-insensitive type strings separated by comma. For instance, + `-PINCLUDE_TEST_TYPES="Python,NUnit"` means to include only Python tests and + NUnit tests. + See `TestTypeEnum` in `build.gradle` for available options. +* `EXCLUDE_TEST_TYPES` - Default to empty string, which means to exclude none. + To add types of tests to exclude, set this properties with + a list of case-insensitive type strings separated by comma. For instance, + `-PEXCLUDE_TEST_TYPES="Python,NUnit"` means to exclude Python tests and NUnit + tests. + See `TestTypeEnum` in `build.gradle` for available options. +* `INCLUDE_TEST_MODULES` - Default to empty string, which means to include the + tests for every modules. To narrow down modules to test, set this properties + with a list of case-insensitive module strings separated by comma. For + instance, `-PINCLUDE_TEST_MODULES="Tool,AndroidResolver"` means to run tests + for tools and Android Resolver only. + See `TestModuleEnum` in `build.gradle` for available options. +* `EXCLUDE_TEST_MODULES` - Default to empty string, which means to exclude none. + To add modules to exclude, set this properties with a list of case-insensitive + module strings separated by comma. For instance, + `-PEXCLUDE_TEST_MODULES="Tool,AndroidResolver"` means to run tests for any + modules other than tools and Android Resolver. + See `TestModuleEnum` in `build.gradle` for available options. +* `EXCLUDE_TESTS` - Default to empty string, which means to exclude none. + To add tests to exclude, set this properties with a list of case-insensitive + test names separated by comma. For instance, + `-PEXCLUDE_TESTS="testGenGuids,testDownloadArtifacts"` means to run tests + except the tests with name of `testGenGuids` and `testDownloadArtifacts`. +* `CONTINUE_ON_FAIL_FOR_TESTS_ENABLED` - Default to `1`. Set to `1` to continue + running the next test when the current one fails. Otherwise, the build script + stops whenever any test fails. + +For instance, by running the following command, it only runs the Unity integration +tests that does not requires GPU, but exclude tests for Android Resolver module +and iOS Resolver module. + +``` +./gradlew test \ + -PINTERACTIVE_MODE_TESTS_ENABLED=0 \ + -PINCLUDE_TEST_TYPES="Integration" \ + -PEXCLUDE_TEST_MODULES="AndroidResolver,iOSResolver" +``` + # Releasing Each time a new build of this plugin is checked into the source tree you diff --git a/build.gradle b/build.gradle index dc89743f..7acdf907 100644 --- a/build.gradle +++ b/build.gradle @@ -223,13 +223,59 @@ project.ext { // Whether to continue to the next test if one fails. continueOnFailForTestsEnabled = - findProperty("CONTINUE_ON_FAIL_FOR_TESTS_ENABLED", "0") == "1" - - // List of failed tests - failedTests = [] - - // List of passed tests - passedTests = [] + findProperty("CONTINUE_ON_FAIL_FOR_TESTS_ENABLED", "1") == "1" + + // List of test sessions + testSessions = [] + + // List of test types that should be included. Controlled by + // "INCLUDE_TEST_TYPES" property. Includes every tests if the property is + // empty. + // DO NOT USE THIS FOR FILTER, Use `actualIncludeTestTypes` instead. + includeTestTypesParam = + TestTypeEnum.toSet( + findProperty("INCLUDE_TEST_TYPES", "").split('\\s+|\\s*,\\s*').toList(), + true) + + // List of test types that should be excluded. Controlled by + // "EXCLUDE_TEST_TYPES" property. Excludes none if the property is + // empty. + // DO NOT USE THIS FOR FILTER, Use `actualIncludeTestTypes` instead. + excludeTestTypesParam = + TestTypeEnum.toSet( + findProperty("EXCLUDE_TEST_TYPES", "").split('\\s+|\\s*,\\s*').toList(), + false) + + // The actual list of test types to run. + actualIncludeTestTypes = includeTestTypesParam.clone() + actualIncludeTestTypes.removeAll(excludeTestTypesParam) + + // List of test modules that should be included. Controlled by + // "INCLUDE_TEST_MODULES" property. Includes every tests if the property is + // empty. + // DO NOT USE THIS FOR FILTER, Use `actualIncludeTestModules` instead. + includeTestModulesParam = + TestModuleEnum.toSet( + findProperty("INCLUDE_TEST_MODULES", "").split('\\s+|\\s*,\\s*').toList(), + true) + + // List of test modules that should be excluded. Controlled by + // "EXCLUDE_TEST_MODULES" property. Excludes none if the property is + // empty. + // DO NOT USE THIS FOR FILTER, Use `actualIncludeTestModules` instead. + excludeTestModulesParam = + TestModuleEnum.toSet( + findProperty("EXCLUDE_TEST_MODULES", "").split('\\s+|\\s*,\\s*').toList(), + false) + + // The actual list of test module to run. + actualIncludeTestModules = includeTestModulesParam.clone() + actualIncludeTestModules.removeAll(excludeTestModulesParam) + + // List of tests to exclude. Controlled by "EXCLUDE_TESTS" property. Excludes + // none if the property is empty. + excludeTestsParam = + new HashSet(findProperty("EXCLUDE_TESTS", "").toLowerCase().split('\\s+|\\s*,\\s*').toList()) // Directory for intermediate and final build outputs. buildDir = new File(scriptDirectory, "build") @@ -337,6 +383,248 @@ public enum OperatingSystem { } } +/* + * Test Types + */ +public enum TestTypeEnum { + INTEGRATION, // Unity Integration Tests using IntegrationTester framework. + NUNIT, // Tests using NUnit framework + PYTHON, // Tests implemented in Python + GRADLE // Tests implemented in Gradle scripts + + // A complete set of all enums + private static HashSet completeSet; + + /* + * Get a complete set of all enums + * + * @returns A complete set of all enums + */ + private static HashSet getCompleteSet() { + if (completeSet == null) { + completeSet = new HashSet() + for (TestTypeEnum type : TestTypeEnum.values()) { + completeSet.add(type); + } + } + return completeSet.clone() + } + + /* + * Convert a list of strings to a set of enums + * + * @param values A list of case-insensitive strings to convert to enum. + * @param completeSetWhenEmpty Whether to return a complete set if the list + * is empty. + * + * @returns A set of enums + */ + public static HashSet toSet( + Collection values, Boolean completeSetWhenEmpty) { + def result = new HashSet() + if ( values == null) { + return completeSetWhenEmpty ? getCompleteSet() : result; + } + for (String value : values) { + def trimmed = value.trim().toUpperCase() + if (!trimmed.isEmpty()) { + result.add(TestTypeEnum.valueOf(trimmed)) + } + } + if (result.size() == 0) { + result = completeSetWhenEmpty ? getCompleteSet() : result; + } + return result + } +} + +/* + * Test Modules + */ +public enum TestModuleEnum { + ANDROIDRESOLVER, // Tests for Android Resolver + VERSIONHANDLER, // Tests for Version Handler + IOSRESOLVER, // Tests for iOS Resolver + PACKAGEMANAGER, // Tests for Package Manager + CORE, // Tests for reusable C# libraries + TOOL // Tests for build/packaging/release tools + + // A complete set of all enums + private static HashSet completeSet; + + /* + * Get a complete set of all enums + * + * @returns A complete set of all enums + */ + private static HashSet getCompleteSet() { + if (completeSet == null) { + completeSet = new HashSet() + for (TestModuleEnum type : TestModuleEnum.values()) { + completeSet.add(type); + } + } + return completeSet.clone() + } + + /* + * Convert a list of strings to a set of enums + * + * @param values A list of case-insensitive strings to convert to enum. + * @param completeSetWhenEmpty Whether to return a complete set if the list + * is empty. + * + * @returns A set of enums + */ + public static HashSet toSet( + Collection values, Boolean completeSetWhenEmpty) { + def result = new HashSet() + if ( values == null) { + return completeSetWhenEmpty ? getCompleteSet() : result; + } + for (String value : values) { + def trimmed = value.trim().toUpperCase() + if (!trimmed.isEmpty()) { + result.add(TestModuleEnum.valueOf(trimmed)) + } + } + if (result.size() == 0) { + result = completeSetWhenEmpty ? getCompleteSet() : result; + } + return result + } +} + +/* + * Determine whether the test should be run given the filter parameters, + * the current test type and the current test module + * + * @param type Type of the test. + * @param module Module of the test. + * + * @returns True if the test should be run by the given the filters. + */ +boolean shouldTestRunWithFilters(TestTypeEnum type, TestModuleEnum module) { + project.ext.actualIncludeTestTypes.contains(type) && + project.ext.actualIncludeTestModules.contains(module) +} + +/* + * Set the test type and module to the given task. + * + * @param task The task to set the properties to. + * @param type Type of the test. + * @param module Module of the test. + */ +void setTestProperties(Task task, TestTypeEnum type, TestModuleEnum module) { + task.ext.testType = type + task.ext.testModule = module +} + +/* + * Unit test for TestTypeEnum + */ +task(testTestTypeEnum) { task -> + setTestProperties(task, TestTypeEnum.GRADLE, TestModuleEnum.TOOL) + doLast { + def expectedTestTypeEnumCompleteSet = + new HashSet([ + TestTypeEnum.INTEGRATION, + TestTypeEnum.NUNIT, + TestTypeEnum.PYTHON, + TestTypeEnum.GRADLE]) + def expectedEmptySet = new HashSet() + def expectedPythonOnlySet = new HashSet([TestTypeEnum.PYTHON]) + def expectedPythonAndIntegrationSet = new HashSet([ + TestTypeEnum.PYTHON, + TestTypeEnum.INTEGRATION]) + + assert TestTypeEnum.getCompleteSet().equals( + expectedTestTypeEnumCompleteSet) + assert TestTypeEnum.toSet([], false).equals( + expectedEmptySet) + assert TestTypeEnum.toSet([], true).equals( + expectedTestTypeEnumCompleteSet) + assert TestTypeEnum.toSet(["python"], false).equals( + expectedPythonOnlySet) + assert TestTypeEnum.toSet(["python"], true).equals( + expectedPythonOnlySet) + assert TestTypeEnum.toSet(["PYTHON"], false).equals( + expectedPythonOnlySet) + assert TestTypeEnum.toSet(["PyThOn"], false).equals( + expectedPythonOnlySet) + assert TestTypeEnum.toSet(["Python", "Integration"], false).equals( + expectedPythonAndIntegrationSet) + assert TestTypeEnum.toSet(["Integration", "Python"], false).equals( + expectedPythonAndIntegrationSet) + assert TestTypeEnum.toSet( + ["Integration", "Python", "Gradle", "NUnit"], false).equals( + expectedTestTypeEnumCompleteSet) + + EvaluateTestResult(task) + } +} + +/* + * Unit test for TestModuleEnum + */ +task(testTestModuleEnum) { task -> + setTestProperties(task, TestTypeEnum.GRADLE, TestModuleEnum.TOOL) + doLast { + def expectedTestModuleEnumCompleteSet = + new HashSet([ + TestModuleEnum.ANDROIDRESOLVER, + TestModuleEnum.VERSIONHANDLER, + TestModuleEnum.IOSRESOLVER, + TestModuleEnum.PACKAGEMANAGER, + TestModuleEnum.CORE, + TestModuleEnum.TOOL]) + def expectedEmptySet = new HashSet() + def expectedToolOnlySet = new HashSet([TestModuleEnum.TOOL]) + def expectedToolAndAndroidResolverSet = new HashSet([ + TestModuleEnum.TOOL, + TestModuleEnum.ANDROIDRESOLVER]) + + assert TestModuleEnum.getCompleteSet().equals( + expectedTestModuleEnumCompleteSet) + assert TestModuleEnum.toSet([], false).equals( + expectedEmptySet) + assert TestModuleEnum.toSet([], true).equals( + expectedTestModuleEnumCompleteSet) + assert TestModuleEnum.toSet(["tool"], false).equals( + expectedToolOnlySet) + assert TestModuleEnum.toSet(["tool"], true).equals( + expectedToolOnlySet) + assert TestModuleEnum.toSet(["TOOL"], false).equals( + expectedToolOnlySet) + assert TestModuleEnum.toSet(["TooL"], false).equals( + expectedToolOnlySet) + assert TestModuleEnum.toSet(["Tool", "AndroidResolver"], false).equals( + expectedToolAndAndroidResolverSet) + assert TestModuleEnum.toSet(["AndroidResolver", "Tool"], false).equals( + expectedToolAndAndroidResolverSet) + assert TestModuleEnum.toSet([ + "AndroidResolver", + "VersionHandler", + "iOSResolver", + "PackageManager", + "Core", + "Tool"], false).equals( + expectedTestModuleEnumCompleteSet) + EvaluateTestResult(task) + } +} + +/* + * Test session + */ +public class TestSession { + public String name; + public TestTypeEnum type; + public TestModuleEnum module; + public Boolean isPassed; +} + /* * Search the path variable for an executable file. * @@ -1097,35 +1385,6 @@ Task createUnityProjectTask(String taskName, Iterable dependsOn, } } -/* - * Setup a Unity project for a testing task and import the plugin in - * preparation for testing. - * - * @param taskName Name of the test task. - * @param dependsOn Dependencies of the new task. - * @param projectName Name of the Unity project to create. - * @param batchMode Whether to run Unity in batch mode. - * - * @returns Task which sets up a Unity project. - * The following extended properties are set on the task: - * - ext.projectDir: Directory of the created Unity project. - * - ext.containerDir: Directory which contains the Unity project and the logs. - * - ext.logFile: Unity log file for the import operation. - */ -Task createSetupUnityProjectTask(String taskName, Iterable dependsOn, - String projectName, Boolean batchMode) { - File outputDir = new File(project.ext.testDir, projectName) - Task createProject = createUnityProjectTask( - sprintf("create%s", taskName), dependsOn, projectName, outputDir) - createProject.with { - inputs.files files(project.ext.pluginExportFile) - } - return createUnityTask( - taskName, "import_plugin", [createProject], projectName, outputDir, - ["-importPackage", project.ext.pluginExportFile.absolutePath, - "-quit"], batchMode, null) -} - /* * Creates a task which runs a test with the Unity plugin. * @@ -1141,14 +1400,17 @@ Task createSetupUnityProjectTask(String taskName, Iterable dependsOn, * project. * @param createTaskClosure Optional task used to start Unity, this must * conform to tasks.create(name, description, type, dependsOn). - * + * @param testType Type of the test + * @param testModule Module of the test +* * @returns Test task. */ Task createUnityTestTask(String taskName, String description, Iterable dependsOn, File testScriptsDir, Iterable editorAssets, Iterable additionalArguments, - Boolean batchMode, createTaskClosure) { + Boolean batchMode, createTaskClosure, + TestTypeEnum testType, TestModuleEnum testModule) { List testScripts = [] if (testScriptsDir) { testScripts = fileTree(testScriptsDir).collect { @@ -1158,10 +1420,20 @@ Task createUnityTestTask(String taskName, String description, } // Setup the Unity project. - Task setupTestProject = createSetupUnityProjectTask( - sprintf("setup%s", taskName), dependsOn, taskName, batchMode) - setupTestProject.with { + File testOutputDir = new File(project.ext.testDir, taskName) + Task createProject = createUnityProjectTask( + sprintf("createsetup%s", taskName), dependsOn, taskName, testOutputDir) + createProject.with { task -> + inputs.files files(project.ext.pluginExportFile) + setTestProperties(task, testType, testModule) + } + Task setupTestProject = createUnityTask( + sprintf("setup%s", taskName), "import_plugin", [createProject], taskName, + testOutputDir, ["-importPackage", project.ext.pluginExportFile.absolutePath, + "-quit"], batchMode, null) + setupTestProject.with { task -> inputs.files (testScripts + editorAssets) + setTestProperties(task, testType, testModule) } List copyTasks = [] @@ -1173,6 +1445,9 @@ Task createUnityTestTask(String taskName, String description, sprintf("Copy the test scripts into the %s Unity project.", taskName), testScripts, testScriptsDir, setupTestProject.ext.projectDir, [setupTestProject], null) + copyTestScripts.with { task -> + setTestProperties(task, testType, testModule) + } copyTasks += [copyTestScripts] } @@ -1183,10 +1458,11 @@ Task createUnityTestTask(String taskName, String description, taskName), type: Copy, dependsOn: [setupTestProject]) - copyEditorAssets.with { + copyEditorAssets.with { task -> from editorAssets into new File(new File(setupTestProject.ext.projectDir, "Assets"), "Editor") + setTestProperties(task, testType, testModule) } copyTasks += [copyEditorAssets] @@ -1199,11 +1475,12 @@ Task createUnityTestTask(String taskName, String description, createTaskClosure, true) testTask.description = description - testTask.with { + testTask.with { task -> finalizedBy reportAllTestsResult doLast { - EvaluateTestResult(testTask) + EvaluateTestResult(task) } + setTestProperties(task, testType, testModule) } // Create a clean task @@ -1230,6 +1507,8 @@ Task createUnityTestTask(String taskName, String description, * @param additionalArguments Additional arguments to pass to Unity. * @param createTaskClosure Optional task used to start Unity, this must * conform to tasks.create(name, description, type, dependsOn). + * @param testType Type of the test + * @param testModule Module of the test * * @returns Test task. */ @@ -1238,7 +1517,9 @@ Task createUnityTestBatchAndNonBatch(String taskName, String description, File testScriptsDir, Iterable editorAssets, Iterable additionalArguments, - createTaskClosure) { + createTaskClosure, + TestTypeEnum testType, + TestModuleEnum testModule) { return tasks.create(name: taskName, description: description, dependsOn: [ @@ -1246,12 +1527,14 @@ Task createUnityTestBatchAndNonBatch(String taskName, String description, sprintf("%sBatchMode", taskName), sprintf("%s (Batch Mode)", description), dependsOn, testScriptsDir, editorAssets, - additionalArguments, true, createTaskClosure), + additionalArguments, true, createTaskClosure, + testType, testModule), createUnityTestTask( sprintf("%sInteractiveMode", taskName), sprintf("%s (Interactive Mode)", description), dependsOn, testScriptsDir, editorAssets, - additionalArguments, false, createTaskClosure)]) + additionalArguments, false, createTaskClosure, + testType, testModule)]) } Task compileResolverLibTests = createXbuildTask( @@ -1264,6 +1547,9 @@ Task compileResolverLibTests = createXbuildTask( [new File("JarResolverTests.dll")], []).with { doFirst { checkNUnitDllPath() } } +compileResolverLibTests.with { task -> + setTestProperties(task, TestTypeEnum.NUNIT, TestModuleEnum.ANDROIDRESOLVER) +} /* * Install Python packages. @@ -1410,6 +1696,9 @@ Task testResolverLibTests = createNUnitTask( "Runs the tests for the deprecated Jar Resolver library", compileResolverLibTests.outputs.files[0], [compileResolverLibTests]) +testResolverLibTests.with { task -> + setTestProperties(task, TestTypeEnum.NUNIT, TestModuleEnum.ANDROIDRESOLVER) +} task cleanResolverLibTests() { description "Clean test output for the deprecated Jar Resolver library" @@ -1417,9 +1706,14 @@ task cleanResolverLibTests() { testResolverLibTests.outputs.files) } } -task testDownloadArtifacts(type: GradleBuild) { +task testDownloadArtifacts(type: GradleBuild) { task -> description "Run tests for the download_artifacts.gradle script." dir "source/AndroidResolver/scripts" + setTestProperties(task, TestTypeEnum.GRADLE, TestModuleEnum.ANDROIDRESOLVER) + doLast { + EvaluateTestResult(task) + } + finalizedBy "reportAllTestsResult" } /* @@ -1432,14 +1726,40 @@ void EvaluateTestResult(Task testTask) { if (testTask.execResult.exitValue != 0) { String errorMsg = sprintf("Test %s FAILED", testTask.name) println sprintf("::error::%s", errorMsg) - project.ext.failedTests.add(testTask.name) + project.ext.testSessions.add(new TestSession( + name: testTask.name, + type: testTask.ext.testType, + module: testTask.ext.testModule, + isPassed: false)) if (!project.ext.continueOnFailForTestsEnabled) { throw new GradleException(errorMsg) } } else { println sprintf("::debug::Test %s PASSED", testTask.name, testTask.execResult.exitValue) - project.ext.passedTests.add(testTask.name) + project.ext.testSessions.add(new TestSession( + name: testTask.name, + type: testTask.ext.testType, + module: testTask.ext.testModule, + isPassed: true)) + } + } else if (testTask.class.simpleName.startsWith("DefaultTask") || + testTask.class.simpleName.startsWith("GradleBuild")) { + if (testTask.state.didWork && testTask.state.failure == null) { + project.ext.testSessions.add(new TestSession( + name: testTask.name, + type: testTask.ext.testType, + module: testTask.ext.testModule, + isPassed: true)) + } else { + project.ext.testSessions.add(new TestSession( + name: testTask.name, + type: testTask.ext.testType, + module: testTask.ext.testModule, + isPassed: false)) } + } else { + throw new GradleException( + sprintf("Unsupported test class %s", testTask.class.simpleName)) } } @@ -1449,17 +1769,26 @@ Task reportAllTestsResult = tasks.create ( type: Task ).with { doLast { - project.ext.passedTests.each { - println sprintf("Test %s PASSED", it) - } - project.ext.failedTests.each { - println sprintf("Test %s FAILED", it) + int failedCount = 0 + int totalCount = 0 + project.ext.testSessions.each { session -> + String resultStr + ++totalCount + if (session.isPassed) { + resultStr = "PASSED" + } else { + resultStr = "FAILED" + ++failedCount + } + println sprintf("Test %s %s [%s/%s]", + session.name, + resultStr, + session.type, + session.module) } - if(project.ext.failedTests.size > 0) { - throw new GradleException( - sprintf("%d out of %d tests failed", - project.ext.failedTests.size, - project.ext.failedTests.size + project.ext.passedTests.size)) + if (failedCount > 0) { + throw new GradleException( + sprintf("%d out of %d tests failed", failedCount, totalCount)) } } } @@ -1471,52 +1800,56 @@ Task testPackageUploader = createPythonTask( new File(project.ext.unityAssetUploaderDir, "unity_asset_uploader_test.py"), [], [], - true).with { + true).with { task -> finalizedBy reportAllTestsResult doLast { - EvaluateTestResult(testPackageUploader) + EvaluateTestResult(task) } + setTestProperties(task, TestTypeEnum.PYTHON, TestModuleEnum.TOOL) } -Task testExportUnityPackage = createPythonTask( +createPythonTask( "testExportUnityPackage", "Test the export_unity_package.py application", [], new File(project.ext.exportUnityPackageDir, "export_unity_package_test.py"), [], exportUnityPackageRequirements, - true).with { + true).with { task -> + setTestProperties(task, TestTypeEnum.PYTHON, TestModuleEnum.TOOL) finalizedBy reportAllTestsResult doLast { - EvaluateTestResult(testExportUnityPackage) + EvaluateTestResult(task) } } -Task testGenGuids = createPythonTask( +createPythonTask( "testGenGuids", "Test the gen_guids.py application", [], new File(project.ext.exportUnityPackageDir, "gen_guids_test.py"), [], ["absl-py"], - true).with { + true).with { task -> + setTestProperties(task, TestTypeEnum.PYTHON, TestModuleEnum.TOOL) finalizedBy reportAllTestsResult doLast { - EvaluateTestResult(testGenGuids) + EvaluateTestResult(task) } } -Task testImportUnityPackage = createPythonTask( +createPythonTask( "testImportUnityPackage", "Test the import_unity_package.py application", [], new File(project.ext.importUnityPackageDir, "import_unity_package_test.py"), [], ["absl-py"], - true).with { + true).with { task -> + setTestProperties(task, TestTypeEnum.PYTHON, TestModuleEnum.TOOL) finalizedBy reportAllTestsResult doLast { - EvaluateTestResult(testImportUnityPackage) + EvaluateTestResult(task) } } @@ -1891,12 +2224,16 @@ Task compileVersionHandlerImplTests = createXbuildTask( [new File("Google.VersionHandlerImplTests.dll")], []).with { doFirst { checkNUnitDllPath() } } - +compileVersionHandlerImplTests.with { task -> + setTestProperties(task, TestTypeEnum.NUNIT, TestModuleEnum.VERSIONHANDLER) +} createNUnitTask( "testVersionHandlerImpl", "Runs tests for the VersionHandlerImpl module", compileVersionHandlerImplTests.outputs.files[0], - [compileVersionHandlerImplTests]) + [compileVersionHandlerImplTests]).with { task -> + setTestProperties(task, TestTypeEnum.NUNIT, TestModuleEnum.VERSIONHANDLER) +} Task compilePackageManagerResolverTests = createXbuildTask( "compilePackageManagerResolverTests", @@ -1911,7 +2248,9 @@ Task compilePackageManagerResolverTests = createXbuildTask( "src")), new File(project.ext.testDir, "PackageManagerResolverTests"), [new File("Google.PackageManagerResolverTests.dll")], - [buildPackageManagerResolver]).with { + [buildPackageManagerResolver]) +compilePackageManagerResolverTests.with { task -> + setTestProperties(task, TestTypeEnum.NUNIT, TestModuleEnum.PACKAGEMANAGER) doFirst { checkNUnitDllPath() } } @@ -1919,7 +2258,9 @@ createNUnitTask( "testPackageManagerResolver", "Runs tests for the PackageManagerResolver module", compilePackageManagerResolverTests.outputs.files[0], - [compilePackageManagerResolverTests]) + [compilePackageManagerResolverTests]).with { task -> + setTestProperties(task, TestTypeEnum.NUNIT, TestModuleEnum.PACKAGEMANAGER) +} createUnityTestBatchAndNonBatch( "testVersionHandlerActivation", @@ -1928,7 +2269,7 @@ createUnityTestBatchAndNonBatch( [buildPlugin], new File(project.ext.scriptDirectory, "source/VersionHandlerImpl/test/activation"), - [], [], null) + [], [], null, TestTypeEnum.INTEGRATION, TestModuleEnum.VERSIONHANDLER) // Launch the test via a script that runs a local web server. createUnityTestBatchAndNonBatch( @@ -1952,7 +2293,7 @@ createUnityTestBatchAndNonBatch( "webrequest_launcher.py"), runnerArgs, [], continueOnFail) - }) + }, TestTypeEnum.INTEGRATION, TestModuleEnum.CORE) createUnityTestBatchAndNonBatch( "testVersionHandlerReflection", @@ -1963,7 +2304,8 @@ createUnityTestBatchAndNonBatch( "source/VersionHandler/test/reflection"), [], [], - null) + null, + TestTypeEnum.INTEGRATION, TestModuleEnum.CORE) Task compileIntegrationTester = createXbuildTask( "compileIntegrationTester", @@ -1992,6 +2334,8 @@ Task compileIntegrationTester = createXbuildTask( * integration test project. * @param arguments Additional arguments for Unity when running the integration * test. + * @param testType Type of the test + * @param testModule Module of the test */ Task createUnityIntegrationTest(String taskName, String description, @@ -2000,7 +2344,9 @@ Task createUnityIntegrationTest(String taskName, Iterable integrationTestProjectSources, Iterable integrationTestProjectOutputs, File unityProjectDir, - Iterable arguments) { + Iterable arguments, + TestTypeEnum testType, + TestModuleEnum testModule) { Task compileIntegrationTest = createXbuildTask( sprintf("compile%s", integrationTestProject), sprintf("Compile %s for %s", integrationTestProject, taskName), @@ -2010,6 +2356,9 @@ Task createUnityIntegrationTest(String taskName, new File(project.ext.buildDir, integrationTestProject), integrationTestProjectOutputs, [compileIntegrationTester] + dependsOn) + compileIntegrationTest.with { task -> + setTestProperties(task, testType, testModule) + } createUnityTestBatchAndNonBatch( taskName, @@ -2018,7 +2367,7 @@ Task createUnityIntegrationTest(String taskName, unityProjectDir, compileIntegrationTest.outputs.files + compileIntegrationTester.outputs.files, - arguments, null) + arguments, null, testType, testModule) } createUnityIntegrationTest( @@ -2034,7 +2383,9 @@ createUnityIntegrationTest( new File( project.ext.scriptDirectory, "source/AndroidResolver/test/AndroidResolverIntegrationTestsUnityProject"), - ["-buildTarget", "android"]) + ["-buildTarget", "android"], + TestTypeEnum.INTEGRATION, + TestModuleEnum.ANDROIDRESOLVER) createUnityIntegrationTest( "testPackageManagerClientIntegrationTests", @@ -2047,7 +2398,9 @@ createUnityIntegrationTest( "PackageManagerClientIntegrationTests")), [new File("Google.PackageManagerClientIntegrationTests.dll"), new File("Google.PackageManagerClientIntegrationTests.dll.mdb")], - null, []) + null, [], + TestTypeEnum.INTEGRATION, + TestModuleEnum.PACKAGEMANAGER) task cleanTests(type: Delete) { description "Clean test directories." @@ -2069,3 +2422,18 @@ project.defaultTasks = ["build", "test", "release", "clean"].collect { task -> task.name.startsWith(topLevelTaskName) }) } + +// Disable tests by filters. +project.tasks.findAll { task -> + if (task.hasProperty("testType") && task.testType != null && + task.hasProperty("testModule") && task.testModule != null) { + if (!shouldTestRunWithFilters(task.testType, task.testModule)) { + println sprintf("DISABLED :%s", task.name) + task.enabled = false + } + if (project.ext.excludeTestsParam.contains(task.name.toLowerCase())) { + println sprintf("DISABLED :%s", task.name) + task.enabled = false + } + } +}