在使用基于 Gradle 的配置时,在 Android Studio (IntelliJ)上运行简单的 JUnit 测试

我使用 Android Studio/IntelliJ来构建一个现有的 Android项目,并希望添加一些简单的 JUnit单元测试。添加此类测试的正确文件夹是什么?

Android Gradle插件定义了一个目录结构,其中 src/main/java用于主源代码,src/instrumentTest/java用于 Android测试。

试图在 InstrentTest 中添加 JUnit 测试对我来说不起作用。我可以运行它作为一个 Android测试(这似乎是该目录) ,但这不是我所寻找的-我只想运行一个简单的 JUnit测试。 我尝试为这个类创建一个 JUnit 运行配置,但是也没有起作用——我猜想是因为我使用的目录被标记为 Android Test 而不是 Source。

如果我创建了一个新的源文件夹,并将其标记为 Project Architecture,那么下次 IntelliJ从 gradle 构建文件中刷新项目配置时,这个文件将被清除。

IntelliJ上基于分级的 android 项目中配置 JUnit 测试的更合适的方法是什么?要使用哪种目录结构?

64192 次浏览

正常情况下,你不能。欢迎来到 Android 的世界,在这里所有的测试都必须在一个设备上运行(除了 Robolecric)。

主要原因是您实际上没有框架的源代码——即使您说服 IDE 在本地运行测试,您也会立即得到一个“ Stub!未实现”例外情况。 “为什么?”你可能会好奇?因为 SDK 提供给您的 android.jar实际上是全部存根化的-所有的类和方法都在那里,但它们都只是抛出一个异常。它只是提供一个 API,而不是提供任何实际的实现。

有一个很棒的项目叫做 机器电学,它实现了很多框架,这样你就可以运行有意义的测试。再加上一个好的模拟框架(例如 Mockito) ,它使你的工作易于管理。

级别插件: https://github.com/robolectric/robolectric-gradle-plugin

介绍

请注意,在编写本文时,Roboleectic 2.4是最新版本,不支持 appcompat v7库。机器人电子3.0版本(还没有预计到达时间)将添加支持。同时 ActionBar Sherlock也会导致机器电学的问题。

要在 Android Studio 中使用 Robolecric,你有两个选择:

(选项1)-使用 Java 模块使用 Android Studio 运行 JUnit 测试

这种技术使用一个 java 模块来进行所有的测试,它依赖于 android 模块,并使用一个定制的测试运行程序来实现一些魔法:

说明可以在这里找到: http://blog.blundellapps.com/how-to-run-robolectric-junit-tests-in-android-studio/

另外,请查看文章末尾的链接,了解如何从 android 工作室运行这些测试。

(选项2)-使用 robolectic-gradle-plugin 在 Android Studio 上运行 JUnit 测试

在 Android Studio 中,我遇到了一些设置 junit 测试以从 gradle 运行的问题。

这是一个非常基本的示例项目,用于在 Android Studio 中基于 gradle 的项目中运行 JUnit 测试: https://github.com/hanscappelle/android-studio-junit-robolectric这是用 Android Studio 0.8.14、 JUnit 4.10、 robolectic gradle plugin 0.13 + 和 robolectic 2.3测试的

Buildscript (project/build.gradle)

构建脚本是项目根目录中的 build.gradle 文件。在那里,我必须将 机器电动梯形插件添加到类路径

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.13.2'


// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'org.robolectric:robolectric-gradle-plugin:0.13.+'


}
}


allprojects {
repositories {
jcenter()
}
}

项目构建脚本(App/build.gradle)

在应用程序模块的构建脚本中,使用 robolectric插件,添加 robolectric配置并添加 androidTestCompile依赖项。

apply plugin: 'com.android.application'
apply plugin: 'robolectric'


android {
// like any other project
}


robolectric {
// configure the set of classes for JUnit tests
include '**/*Test.class'
exclude '**/espresso/**/*.class'


// configure max heap size of the test JVM
maxHeapSize = '2048m'


// configure the test JVM arguments
jvmArgs '-XX:MaxPermSize=512m', '-XX:-UseSplitVerifier'


// configure whether failing tests should fail the build
ignoreFailures true


// use afterTest to listen to the test execution results
afterTest { descriptor, result ->
println "Executing test for {$descriptor.name} with result: ${result.resultType}"
}
}


dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])


androidTestCompile 'org.robolectric:robolectric:2.3'
androidTestCompile 'junit:junit:4.10'
}

创建 JUnit 测试类

现在将测试类放在默认位置(或更新 gradle 配置)

app/src/androidTest/java

并命名以 Test (或者再次更新配置)结尾的测试类,扩展 junit.framework.TestCase并用 @Test注释测试方法。

package be.hcpl.android.mytestedapplication;


import junit.framework.TestCase;
import org.junit.Test;


public class MainActivityTest extends TestCase {


@Test
public void testThatSucceeds(){
// all OK
assert true;
}


@Test
public void testThatFails(){
// all NOK
assert false;
}
}

执行测试

接下来使用 gradlew from 命令行执行测试(如果需要,使用 chmod +x使其可执行)

./gradlew clean test

输出样本:

Executing test for {testThatSucceeds} with result: SUCCESS
Executing test for {testThatFails} with result: FAILURE


android.hcpl.be.mytestedapplication.MainActivityTest > testThatFails FAILED
java.lang.AssertionError at MainActivityTest.java:21


2 tests completed, 1 failed
There were failing tests. See the report at: file:///Users/hcpl/Development/git/MyTestedApplication/app/build/test-report/debug/index.html
:app:test


BUILD SUCCESSFUL

故障排除

替代源目录替代源目录

就像你可以把你的 java 源文件放在其他地方一样,你可以移动你的测试源文件。只需更新级别 sourceSets配置。

    sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}


androidTest {
setRoot('tests')
}
}

包 org.junit 不存在

您忘记在应用程序构建脚本中添加 junit 测试依赖项

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])


androidTestCompile 'org.robolectric:robolectric:2.3'
androidTestCompile 'junit:junit:4.10'
}

异常: 存根!

使用来自 Android Studio 的运行配置而不是命令行(Android Studio 中的 Terminal 选项卡)运行此测试。要从 Android Studio 运行它,您必须更新 app.iml文件,以便在底部列出 jdk 条目。详情请参阅 Deckard 等级的例子

完整错误示例:

!!! JUnit version 3.8 or later expected:


java.lang.RuntimeException: Stub!
at junit.runner.BaseTestRunner.<init>(BaseTestRunner.java:5)
at junit.textui.TestRunner.<init>(TestRunner.java:54)
at junit.textui.TestRunner.<init>(TestRunner.java:48)
at junit.textui.TestRunner.<init>(TestRunner.java:41)
at com.intellij.rt.execution.junit.JUnitStarter.junitVersionChecks(JUnitStarter.java:190)
at com.intellij.rt.execution.junit.JUnitStarter.canWorkWithJUnitVersion(JUnitStarter.java:173)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

错误: JAVA _ HOME 被设置为无效目录

有关解决方案,请参见 这个所以问题:

export JAVA_HOME=`/usr/libexec/java_home -v 1.7`

完整的错误日志:

ERROR: JAVA_HOME is set to an invalid directory: export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home


Please set the JAVA_HOME variable in your environment to match the
location of your Java installation.

未找到测试类

如果你想在 Android Studio Junit 测试运行器上运行你的测试,你需要扩展 build.gradle 文件,这样 Android 工作室就可以找到你编译好的测试类:

sourceSets {
testLocal {
java.srcDir file('src/test/java')
resources.srcDir file('src/test/resources')
}
}


android {


// tell Android studio that the instrumentTest source set is located in the unit test source set
sourceSets {
instrumentTest.setRoot('src/test')
}
}


dependencies {


// Dependencies for the `testLocal` task, make sure to list all your global dependencies here as well
testLocalCompile 'junit:junit:4.11'
testLocalCompile 'com.google.android:android:4.1.1.4'
testLocalCompile 'org.robolectric:robolectric:2.3'


// Android Studio doesn't recognize the `testLocal` task, so we define the same dependencies as above for instrumentTest
// which is Android Studio's test task
androidTestCompile 'junit:junit:4.11'
androidTestCompile 'com.google.android:android:4.1.1.4'
androidTestCompile 'org.robolectric:robolectric:2.3'


}


task localTest(type: Test, dependsOn: assemble) {
testClassesDir = sourceSets.testLocal.output.classesDir


android.sourceSets.main.java.srcDirs.each { dir ->
def buildDir = dir.getAbsolutePath().split('/')
buildDir =  (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/')


sourceSets.testLocal.compileClasspath += files(buildDir)
sourceSets.testLocal.runtimeClasspath += files(buildDir)
}


classpath = sourceSets.testLocal.runtimeClasspath
}


check.dependsOn localTest

发信人: http://kostyay.name/android-studio-robolectric-gradle-getting-work/

更多的资源

我在这方面找到的最好的文章是:

从 Android Studio 1.1开始,答案很简单: Http://tools.android.com/tech-docs/unit-testing-support

Android Studio 现在支持这一点,从 Android Gradle 插件1.1.0开始,看看这个:

Https://developer.android.com/training/testing/unit-testing/local-unit-tests.html

在 GitHub 上进行本地单元测试的示例应用程序:

Https://github.com/googlesamples/android-testing/tree/master/unittesting/basicsample

对于 Android Studio 1.2 + 来说,为 JUnit 很简单设置一个项目,请尝试遵循以下教程:

这是为 JUnit 设置项目最简单的部分:

Https://io2015codelabs.appspot.com/codelabs/android-studio-testing#1

沿着过去的连结,直至「 做测试」为止

现在,如果您想要集成内部测试,请按照下面的步骤:

Https://io2015codelabs.appspot.com/codelabs/android-studio-testing#6

请从 Android 开发者官方站点查看这个 教程。本文还展示了如何为测试创建模型。

顺便说一下,您应该注意到简单 JUnit 测试的依赖项范围应该是“ testCompile”。