Support for running JUnit tests.
- Enable "Gradle-aware make" step in JUnit run configurations.
- Make it run the correct Gradle task.
- Set the correct compiler test output path in android modules.
- a JUnitPatcher that removes stub android.jar from the
test classpath.
- Don't offer android instrumentation test configurations when
the selected artifact is "unit tests".
- Fix BuildVariantView layout.
Change-Id: I02fc9f7c3a7512b4b7162bddb78bff9dc6bd589b
(cherry picked from commit be2339152df0f20ee336d37199a1ce7d896b4ba9)
diff --git a/android/src/META-INF/plugin.xml b/android/src/META-INF/plugin.xml
index 6c954ca..eaa39fd 100755
--- a/android/src/META-INF/plugin.xml
+++ b/android/src/META-INF/plugin.xml
@@ -664,6 +664,7 @@
<spellchecker.support language="Groovy" implementationClass="org.jetbrains.android.spellchecker.AndroidGradleSpellcheckingStrategy" order="first"/>
<deadCode implementation="org.jetbrains.android.inspections.AndroidComponentEntryPoint"/>
<testSrcLocator implementation="org.jetbrains.android.run.testing.AndroidTestLocationProvider"/>
+ <junitPatcher implementation="org.jetbrains.android.run.testing.AndroidJunitPatcher" />
<virtualFileSystem key="android-dummy" implementationClass="com.android.tools.idea.editors.AndroidFakeFileSystem"/>
</extensions>
diff --git a/android/src/com/android/tools/idea/gradle/customizer/android/CompilerOutputModuleCustomizer.java b/android/src/com/android/tools/idea/gradle/customizer/android/CompilerOutputModuleCustomizer.java
index f182500..2111dc9 100644
--- a/android/src/com/android/tools/idea/gradle/customizer/android/CompilerOutputModuleCustomizer.java
+++ b/android/src/com/android/tools/idea/gradle/customizer/android/CompilerOutputModuleCustomizer.java
@@ -15,6 +15,7 @@
*/
package com.android.tools.idea.gradle.customizer.android;
+import com.android.builder.model.BaseArtifact;
import com.android.builder.model.Variant;
import com.android.tools.idea.gradle.IdeaAndroidProject;
import com.android.tools.idea.gradle.customizer.AbstractCompileOutputModuleCustomizer;
@@ -44,8 +45,11 @@
return;
}
Variant selectedVariant = androidProject.getSelectedVariant();
- File outputFile = selectedVariant.getMainArtifact().getClassesFolder();
- setOutputPaths(module, outputFile, null);
+ File mainClassesFolder = selectedVariant.getMainArtifact().getClassesFolder();
+ BaseArtifact testArtifact = androidProject.findSelectedTestArtifact(selectedVariant);
+ File testClassesFolder = testArtifact == null ? null : testArtifact.getClassesFolder();
+
+ setOutputPaths(module, mainClassesFolder, testClassesFolder);
}
@Override
diff --git a/android/src/com/android/tools/idea/gradle/invoker/GradleInvoker.java b/android/src/com/android/tools/idea/gradle/invoker/GradleInvoker.java
index 55b3a13..d8df831 100644
--- a/android/src/com/android/tools/idea/gradle/invoker/GradleInvoker.java
+++ b/android/src/com/android/tools/idea/gradle/invoker/GradleInvoker.java
@@ -280,7 +280,7 @@
tasks.add(createBuildTask(gradlePath, properties.COMPILE_JAVA_TASK_NAME));
}
- if (testCompileType == TestCompileType.ANDROID_TESTS) {
+ if (testCompileType != TestCompileType.NONE) {
String gradleTaskName = properties.ASSEMBLE_TEST_TASK_NAME;
if (StringUtil.isNotEmpty(gradleTaskName)) {
tasks.add(createBuildTask(gradlePath, gradleTaskName));
diff --git a/android/src/com/android/tools/idea/gradle/run/MakeBeforeRunTaskProvider.java b/android/src/com/android/tools/idea/gradle/run/MakeBeforeRunTaskProvider.java
index 42f67a8..6c4d795 100644
--- a/android/src/com/android/tools/idea/gradle/run/MakeBeforeRunTaskProvider.java
+++ b/android/src/com/android/tools/idea/gradle/run/MakeBeforeRunTaskProvider.java
@@ -30,6 +30,7 @@
import com.intellij.execution.BeforeRunTaskProvider;
import com.intellij.execution.configurations.ModuleBasedConfiguration;
import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.junit.JUnitConfiguration;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
@@ -42,6 +43,7 @@
import com.intellij.util.concurrency.Semaphore;
import icons.AndroidIcons;
import org.jetbrains.android.run.AndroidRunConfigurationBase;
+import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -107,7 +109,11 @@
@Override
public MakeBeforeRunTask createTask(RunConfiguration runConfiguration) {
// "Gradle-aware Make" is only available in Android Studio.
- if (AndroidStudioSpecificInitializer.isAndroidStudio() && runConfiguration instanceof AndroidRunConfigurationBase) {
+ if (AndroidStudioSpecificInitializer.isAndroidStudio()
+ // Enable "Gradle-aware Make" only for android configurations...
+ && (runConfiguration instanceof AndroidRunConfigurationBase ||
+ // ...and JUnit configurations if unit-testing support is enabled.
+ (AndroidUtils.isUnitTestingSupportEnabled() && runConfiguration instanceof JUnitConfiguration))) {
return new MakeBeforeRunTask();
} else {
return null;
diff --git a/android/src/org/jetbrains/android/run/testing/AndroidJunitPatcher.java b/android/src/org/jetbrains/android/run/testing/AndroidJunitPatcher.java
new file mode 100644
index 0000000..160a790
--- /dev/null
+++ b/android/src/org/jetbrains/android/run/testing/AndroidJunitPatcher.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.android.run.testing;
+
+import com.android.builder.model.AndroidProject;
+import com.android.sdklib.IAndroidTarget;
+import com.android.tools.idea.gradle.IdeaAndroidProject;
+import com.intellij.execution.JUnitPatcher;
+import com.intellij.execution.configurations.JavaParameters;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.SdkAdditionalData;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.util.PathsList;
+import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.sdk.AndroidPlatform;
+import org.jetbrains.android.sdk.AndroidSdkAdditionalData;
+import org.jetbrains.android.sdk.AndroidSdkType;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Implementation of {@link com.intellij.execution.JUnitPatcher} that removes android.jar from the class path. It's only applicable to
+ * JUnit run configurations if the selected test artifact is "unit tests". In this case, the mockable android.jar is already in the
+ * dependencies (taken from the model).
+ */
+public class AndroidJunitPatcher extends JUnitPatcher {
+ @Override
+ public void patchJavaParameters(@Nullable Module module, JavaParameters javaParameters) {
+ if (module == null) {
+ return;
+ }
+
+ AndroidFacet androidFacet = AndroidFacet.getInstance(module);
+ if (androidFacet == null) {
+ return;
+ }
+
+ IdeaAndroidProject ideaAndroidProject = androidFacet.getIdeaAndroidProject();
+ if (ideaAndroidProject == null) {
+ return;
+ }
+
+ // Modify the class path only if we're dealing with the unit test artifact.
+ if (!ideaAndroidProject.getSelectedTestArtifactName().equals(AndroidProject.ARTIFACT_UNIT_TEST)) {
+ return;
+ }
+
+ final PathsList classPath = javaParameters.getClassPath();
+
+ final Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
+ if (sdk == null || !(sdk.getSdkType() instanceof AndroidSdkType)) {
+ return;
+ }
+
+ final SdkAdditionalData data = sdk.getSdkAdditionalData();
+ if (!(data instanceof AndroidSdkAdditionalData)) {
+ return;
+ }
+
+ final AndroidPlatform platform = ((AndroidSdkAdditionalData)data).getAndroidPlatform();
+ if (platform == null) {
+ return;
+ }
+
+ classPath.remove(platform.getTarget().getPath(IAndroidTarget.ANDROID_JAR));
+ }
+}
diff --git a/android/src/org/jetbrains/android/run/testing/AndroidTestConfigurationProducer.java b/android/src/org/jetbrains/android/run/testing/AndroidTestConfigurationProducer.java
index 4f4d664..3b13e0c 100644
--- a/android/src/org/jetbrains/android/run/testing/AndroidTestConfigurationProducer.java
+++ b/android/src/org/jetbrains/android/run/testing/AndroidTestConfigurationProducer.java
@@ -16,6 +16,8 @@
package org.jetbrains.android.run.testing;
+import com.android.builder.model.AndroidProject;
+import com.android.tools.idea.gradle.IdeaAndroidProject;
import com.intellij.execution.JavaExecutionUtil;
import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
@@ -142,6 +144,7 @@
if (module == null) {
return false;
}
+
Location location = context.getLocation();
if (location == null) {
@@ -159,6 +162,12 @@
return false;
}
+ IdeaAndroidProject ideaAndroidProject = facet.getIdeaAndroidProject();
+ if (ideaAndroidProject != null && !ideaAndroidProject.getSelectedTestArtifactName().equals(AndroidProject.ARTIFACT_ANDROID_TEST)) {
+ // Only suggest the android test run configuration if it makes sense for the selected test artifact.
+ return false;
+ }
+
setupInstrumentationTestRunner(configuration, facet);
if (setupAllInPackageConfiguration(configuration, element, context, sourceElement)) {
return true;
diff --git a/android/src/org/jetbrains/android/util/AndroidUtils.java b/android/src/org/jetbrains/android/util/AndroidUtils.java
index 8ba5585..be048a4 100644
--- a/android/src/org/jetbrains/android/util/AndroidUtils.java
+++ b/android/src/org/jetbrains/android/util/AndroidUtils.java
@@ -272,7 +272,7 @@
configuration.PREFERRED_AVD = preferredAvdName;
}
runManager.addConfiguration(settings, false);
- runManager.setActiveConfiguration(settings);
+ runManager.setSelectedConfiguration(settings);
}
};
if (!ask) {
diff --git a/android/testData/guiTests/SimpleApplicationWithUnitTests/app/build.gradle b/android/testData/guiTests/SimpleApplicationWithUnitTests/app/build.gradle
index 224b369..27ed973 100644
--- a/android/testData/guiTests/SimpleApplicationWithUnitTests/app/build.gradle
+++ b/android/testData/guiTests/SimpleApplicationWithUnitTests/app/build.gradle
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
apply plugin: 'com.android.application'
android {
diff --git a/android/testData/guiTests/SimpleApplicationWithUnitTests/app/src/main/res/menu/my.xml b/android/testData/guiTests/SimpleApplicationWithUnitTests/app/src/main/res/menu/my.xml
index bea58cc..9a98b1d 100644
--- a/android/testData/guiTests/SimpleApplicationWithUnitTests/app/src/main/res/menu/my.xml
+++ b/android/testData/guiTests/SimpleApplicationWithUnitTests/app/src/main/res/menu/my.xml
@@ -1,3 +1,18 @@
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MyActivity" >
diff --git a/android/testData/guiTests/SimpleApplicationWithUnitTests/settings.gradle b/android/testData/guiTests/SimpleApplicationWithUnitTests/settings.gradle
index e7b4def..7a4f23d 100644
--- a/android/testData/guiTests/SimpleApplicationWithUnitTests/settings.gradle
+++ b/android/testData/guiTests/SimpleApplicationWithUnitTests/settings.gradle
@@ -1 +1,16 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
include ':app'