Rework the way tests are installed and run.
Xavier Ducrohet [Fri, 21 Sep 2012 20:28:40 +0000 (13:28 -0700)]
It used to do:
    Install all, run all, uninstall all.
It now does:
   foreach variant: install, run, uninstall.

This allows to properly test different flavors that share the same
package name. Before installAll would override some packages with new
ones and only the last installed flavor would be installed.

Note that right now this relies on dependsOn to do the install, run
and uninstall in the proper order which is not reliable so this
needs to be fixed.

Also, we'll want to change this later to support deploying to
multiple emulators.

Change-Id: I0931b3a9b7a0cbd37c2e763e4abf768777342b37

gradle/src/main/groovy/com/android/build/gradle/AndroidBasePlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/AndroidPlugin.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/ApplicationVariant.groovy
gradle/src/main/groovy/com/android/build/gradle/internal/ProductionAppVariant.groovy

index 575ddc6..d8cbda6 100644 (file)
@@ -29,6 +29,7 @@ import com.android.builder.ProductFlavor
 import com.android.builder.SdkParser
 import com.android.builder.VariantConfiguration
 import com.android.utils.ILogger
+import org.gradle.api.DefaultTask
 import org.gradle.api.GradleException
 import org.gradle.api.Project
 import org.gradle.api.Task
@@ -60,8 +61,6 @@ abstract class AndroidBasePlugin {
     protected SourceSet mainSourceSet
     protected SourceSet testSourceSet
 
-    protected Task installAllForTests
-    protected Task runAllTests
     protected Task uninstallAll
     protected Task assembleTest
 
@@ -79,19 +78,9 @@ abstract class AndroidBasePlugin {
 
         findSdk(project)
 
-        installAllForTests = project.tasks.add("installAllForTests")
-        installAllForTests.group = "Verification"
-        installAllForTests.description = "Installs all applications needed to run tests."
-
-        runAllTests = project.tasks.add("runAllTests")
-        runAllTests.group = "Verification"
-        runAllTests.description = "Runs all tests."
-
         uninstallAll = project.tasks.add("uninstallAll")
         uninstallAll.description = "Uninstall all applications."
-        uninstallAll.group = "Install"
-
-        project.tasks.check.dependsOn installAllForTests, runAllTests
+        uninstallAll.group = INSTALL_GROUP
     }
 
     protected setDefaultConfig(ProductFlavor defaultConfig) {
@@ -357,21 +346,43 @@ abstract class AndroidBasePlugin {
         createCompileTask(variant, testedVariant, processResources, generateBuildConfigTask,
                 compileAidl)
 
-        Task assembleTask = addPackageTasks(variant, null, true /*isTestApk*/)
+        addPackageTasks(variant, null)
 
         if (assembleTest != null) {
-            assembleTest.dependsOn assembleTask
+            assembleTest.dependsOn variant.assembleTask
         }
 
-        def runTestsTask = project.tasks.add("Run${variant.name}Tests", RunTestsTask)
+        // create the check task for this test
+        def checkTask = project.tasks.add("check${testedVariant.name}", DefaultTask)
+        checkTask.description = "Installs and runs the checks for Build ${testedVariant.name}."
+        checkTask.group = JavaBasePlugin.VERIFICATION_GROUP
+
+        checkTask.dependsOn testedVariant.assembleTask, variant.assembleTask
+        project.tasks.check.dependsOn checkTask
+
+        // now run the test.
+        def runTestsTask = project.tasks.add("run${testedVariant.name}Tests", RunTestsTask)
+        runTestsTask.description = "Runs the checks for Build ${testedVariant.name}. Must be installed on device."
+        runTestsTask.group = JavaBasePlugin.VERIFICATION_GROUP
         runTestsTask.sdkDir = sdkDir
         runTestsTask.variant = variant
+        checkTask.doLast { runTestsTask }
 
-        runAllTests.dependsOn runTestsTask
+        // TODO: don't rely on dependsOn which isn't reliable for execution order.
+        if (testedVariant.config.type == VariantConfiguration.Type.DEFAULT) {
+            checkTask.dependsOn testedVariant.installTask, variant.installTask, runTestsTask, testedVariant.uninstallTask, variant.uninstallTask
+        } else {
+            checkTask.dependsOn variant.installTask, runTestsTask, variant.uninstallTask
+        }
     }
 
-    protected Task addPackageTasks(ApplicationVariant variant, Task assembleTask,
-                                   boolean isTestApk) {
+    /**
+     * Creates the packaging tasks for the given Variant.
+     * @param variant the variant.
+     * @param assembleTask an optional assembleTask to be used. If null a new one is created. The
+     *                assembleTask is always set in the Variant.
+     */
+    protected void addPackageTasks(ApplicationVariant variant, Task assembleTask) {
         // Add a dex task
         def dexTaskName = "dex${variant.name}"
         def dexTask = project.tasks.add(dexTaskName, DexTask)
@@ -423,38 +434,34 @@ abstract class AndroidBasePlugin {
             }
 
             // Add a task to install the application package
-            def installApp = project.tasks.add("install${variant.name}", InstallTask)
-            installApp.description = "Installs the " + variant.description
-            installApp.group = "Install"
-            installApp.dependsOn appTask
-            installApp.conventionMapping.packageFile = { appTask.outputFile }
-            installApp.sdkDir = sdkDir
-
-            if (isTestApk) {
-                installAllForTests.dependsOn installApp
-            }
+            def installTask = project.tasks.add("install${variant.name}", InstallTask)
+            installTask.description = "Installs the " + variant.description
+            installTask.group = INSTALL_GROUP
+            installTask.dependsOn appTask
+            installTask.conventionMapping.packageFile = { appTask.outputFile }
+            installTask.sdkDir = sdkDir
+
+            variant.installTask = installTask
         }
 
         // Add an assemble task
-        Task returnTask = null
         if (assembleTask == null) {
             assembleTask = project.tasks.add("assemble${variant.name}")
             assembleTask.description = "Assembles the " + variant.description
             assembleTask.group = BasePlugin.BUILD_GROUP
-            returnTask = assembleTask
         }
         assembleTask.dependsOn appTask
+        variant.assembleTask = assembleTask
 
         // add an uninstall task
-        def uninstallApp = project.tasks.add("uninstall${variant.name}", UninstallTask)
-        uninstallApp.description = "Uninstalls the " + variant.description
-        uninstallApp.group = AndroidBasePlugin.INSTALL_GROUP
-        uninstallApp.variant = variant
-        uninstallApp.sdkDir = sdkDir
-
-        uninstallAll.dependsOn uninstallApp
-
-        return returnTask
+        def uninstallTask = project.tasks.add("uninstall${variant.name}", UninstallTask)
+        uninstallTask.description = "Uninstalls the " + variant.description
+        uninstallTask.group = INSTALL_GROUP
+        uninstallTask.variant = variant
+        uninstallTask.sdkDir = sdkDir
+
+        variant.uninstallTask = uninstallTask
+        uninstallAll.dependsOn uninstallTask
     }
 
     PrepareDependenciesTask createPrepareDependenciesTask(ProductionAppVariant variant) {
index 615f4ad..7d31e86 100644 (file)
@@ -181,12 +181,10 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
                     defaultConfigData.productFlavor, defaultConfigData.androidSourceSet,
                     buildTypeData.buildType, buildTypeData.androidSourceSet)
 
-            boolean isTestedVariant = (buildTypeData == testData)
-
             ProductionAppVariant productionAppVariant = addVariant(variantConfig,
-                    buildTypeData.assembleTask, isTestedVariant)
+                    buildTypeData.assembleTask)
 
-            if (isTestedVariant) {
+            if (buildTypeData == testData) {
                 testedVariant = productionAppVariant
             }
         }
@@ -232,10 +230,7 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
                 variantConfig.addProductFlavor(data.productFlavor, data.androidSourceSet)
             }
 
-            boolean isTestedVariant = (buildTypeData == testData)
-
-            ProductionAppVariant productionAppVariant = addVariant(variantConfig, null,
-                    isTestedVariant)
+            ProductionAppVariant productionAppVariant = addVariant(variantConfig, null)
 
             buildTypeData.assembleTask.dependsOn productionAppVariant.assembleTask
 
@@ -246,7 +241,7 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
             }
             assembleTask.dependsOn productionAppVariant.assembleTask
 
-            if (isTestedVariant) {
+            if (buildTypeData == testData) {
                 testedVariant = productionAppVariant
             }
         }
@@ -282,13 +277,10 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
     /**
      * Creates build tasks for a given variant.
      * @param variantConfig
-     * @param assembleTask an optional assembleTask to be used. If null, a new one is created in the
-     *                     returned ProductAppVariant instance.
-     * @param isTestApk whether this apk is needed for running tests
+     * @param assembleTask an optional assembleTask to be used. If null, a new one is created.
      * @return
      */
-    private ProductionAppVariant addVariant(VariantConfiguration variantConfig, Task assembleTask,
-                                            boolean isTestApk) {
+    private ProductionAppVariant addVariant(VariantConfiguration variantConfig, Task assembleTask) {
 
         def variant = new ProductionAppVariant(variantConfig)
 
@@ -316,10 +308,7 @@ class AndroidPlugin extends AndroidBasePlugin implements Plugin<Project> {
         createCompileTask(variant, null/*testedVariant*/, processResources, generateBuildConfigTask,
                 compileAidl)
 
-        Task returnTask = addPackageTasks(variant, assembleTask, isTestApk)
-        if (returnTask != null) {
-            variant.assembleTask = returnTask
-        }
+        addPackageTasks(variant, assembleTask)
 
         return variant;
     }
index 907c511..e7504e9 100644 (file)
@@ -17,10 +17,11 @@ package com.android.build.gradle.internal
 
 import com.android.build.gradle.AndroidBasePlugin
 import com.android.builder.AndroidBuilder
+import com.android.builder.ProductFlavor
 import com.android.builder.VariantConfiguration
+import org.gradle.api.Task
 import org.gradle.api.file.FileCollection
 import org.gradle.api.tasks.compile.Compile
-import com.android.builder.ProductFlavor
 
 /**
  * Represents something that can be packaged into an APK and installed.
@@ -33,6 +34,9 @@ public abstract class ApplicationVariant {
     FileCollection resourcePackage
     Compile compileTask
     Iterable<Object> configObjects
+    Task assembleTask
+    Task installTask
+    Task uninstallTask
 
     ApplicationVariant(VariantConfiguration config) {
         this.config = config
index ef6fb11..f6abaca 100644 (file)
@@ -18,11 +18,9 @@ package com.android.build.gradle.internal
 import com.android.build.gradle.AndroidBasePlugin
 import com.android.builder.AndroidBuilder
 import com.android.builder.VariantConfiguration
-import org.gradle.api.Task
 
 class ProductionAppVariant extends ApplicationVariant {
     final String name
-    Task assembleTask
 
     ProductionAppVariant(VariantConfiguration config) {
         super(config)