79

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

androidGradle插件为主要源代码和测试定义了一个目录src/main/java结构。src/instrumentTest/javaAndroid

尝试在 instrumentTest 中添加我的 JUnit 测试对我不起作用。我可以将它作为Android测试运行(这就是该目录的用途),但这不是我想要的——我只想运行一个简单的JUnit测试。我尝试为这个类创建一个 JUnit 运行配置,但这也没有用——我想是因为我使用的是一个标记为AndroidTest 而不是 Source 的目录。

如果我创建一个新的源文件夹并在项目结构中将其标记为这样,则下次IntelliJ从 gradle 构建文件刷新项目配置时,这将被擦除。

在基于 gradle 的 android 项目中配置 JUnit 测试的更合适的方法是IntelliJ什么?为此使用哪个目录结构?

4

6 回答 6

36

通常,你不能。欢迎来到 Android 世界,所有测试都必须在设备上运行(Robolectric 除外)。

主要原因是您实际上没有框架的源代码——即使您说服 IDE 在本地运行测试,您也会立即收到“存根!未实现”异常。“为什么?” 你可能想知道?因为android.jarSDK 为您提供的内容实际上都被删除了 - 所有的类和方法都在那里,但它们都只是抛出一个异常。它提供了一个 API,但没有提供任何实际的实现。

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

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

于 2013-07-24T22:01:59.667 回答
32

介绍

请注意,在撰写本文时,robolectric 2.4 是最新版本,不支持appcompat v7库。将在 robolectric 3.0 版本中添加支持(尚无 ETA)。也ActionBar Sherlock可能导致 robolectric 出现问题。

要在 Android Studio 中使用 Robolectric,您有 2 个选项:

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

该技术使用 java 模块进行所有测试,并依赖于您的 android 模块和具有一些魔力的自定义测试运行器:

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

还要检查该帖子末尾的链接,以从 android studio 运行测试。

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

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

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

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

构建脚本是项目根目录中的 build.gradle 文件。在那里我不得不将robolectric 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;
    }
}

执行测试

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

./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 源文件放在其他地方一样,您可以移动测试源文件。只需更新 gradlesourceSets配置。

    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'
}

java.lang.RuntimeException:存根!

您正在使用来自 Android Studio 的运行配置而不是命令行(Android Studio 中的终端选项卡)运行此测试。要从 Android Studio 运行它,您必须更新app.iml文件以在底部列出 jdk 条目。有关详细信息,请参阅deckard-gradle 示例

完整的错误示例:

!!! 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 设置为无效目录

请参阅此 SO question以获取解决方案。将以下导出添加到您的 bash 配置文件:

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 Test runner 运行你的测试,你必须扩展 build.gradle 文件,以便 android studio 可以找到你编译的测试类:

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/

更多资源

我发现的最好的文章是:

于 2014-11-03T15:18:28.207 回答
23

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

于 2015-02-11T20:53:48.653 回答
3

从 Android Gradle 插件 1.1.0 开始,Android Studio 现在支持此功能,请查看:

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

GitHub 上带有本地单元测试的示例应用程序:

https://github.com/googlesamples/android-testing/tree/master/unittesting/BasicSample

于 2015-05-16T08:07:51.280 回答
1

对于Android Studio 1.2+,为 JUnit 设置项目非常简单,请尝试按照本教程进行操作:

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

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

跟随过去的链接直到“运行你的测试

现在,如果您想与仪器测试集成,请从这里开始:

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

于 2015-09-09T00:50:58.743 回答
0

请参阅 Android Developers 官方网站上的本教程。本文还展示了如何为您的测试创建模型。

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

于 2015-12-09T01:36:06.410 回答