我正在使用Android Studio/IntelliJ
构建现有的Android
项目,并希望添加一些简单的JUnit
单元测试。添加此类测试的正确文件夹是什么?
android Gradle
插件定义了一个目录结构,主要源代码为src/main/java
,src/instrumentTest/java
测试为Android
。
尝试在instrumentTest中添加我的JUnit测试对我来说不起作用。我可以将它作为Android
测试运行(这就是该目录所针对的),但这不是我想要的 - 我只想运行一个简单的JUnit
测试。
我尝试为这个类创建一个JUnit运行配置但是也没有用 - 我想是因为我使用的标记为Android
Test的目录而不是Source。
如果我在项目结构中创建一个新的源文件夹并将其标记为这样,那么下次IntelliJ
从gradle构建文件刷新项目配置时将会擦除此文件夹。
在IntelliJ
的基于gradle的android项目中配置JUnit测试的更合适的方法是什么?使用哪种目录结构?
答案 0 :(得分:36)
通常情况下,你不能。欢迎来到Android世界,所有测试都必须在设备上运行(Robolectric除外)。
主要原因是您实际上没有框架的源 - 即使您说服IDE在本地运行测试,您也会立即获得“Stub!Not implemented”异常。
“为什么?”你可能想知道?因为SDK提供给你的android.jar
实际上都是存根的 - 所有的类和方法都存在但是它们都只是抛出异常。它提供了一个API,但没有给你任何实际的实现。
有一个名为Robolectric的精彩项目,它实现了很多框架,因此您可以运行有意义的测试。再加上一个好的模拟框架(例如,Mockito),它可以让你的工作变得易于管理。
Gradle插件:https://github.com/robolectric/robolectric-gradle-plugin
答案 1 :(得分:32)
请注意,在撰写本文时,robolectric 2.4是最新版本,不支持appcompat v7
库。支持将添加到robolectric 3.0版本中(还没有ETA )。同样ActionBar Sherlock
会导致robolectric出现问题。
要在Android Studio中使用Robolectric,您有两个选择:
这种技术使用java模块进行所有测试,依赖于你的android模块和一个带有魔法的自定义测试运行器:
说明可在此处找到:http://blog.blundellapps.com/how-to-run-robolectric-junit-tests-in-android-studio/
同时检查该帖子末尾的链接,以便从android studio运行测试。
我在Android Studio中设置了从gradle运行的junit测试时遇到了一些问题。
这是一个非常基本的示例项目,用于在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进行测试的/ p>
构建脚本是项目根目录中的build.gradle文件。在那里我必须将robolectric gradle plugin添加到classpath
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()
}
}
在您的应用模块的构建脚本中,使用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'
}
现在将测试类放在默认位置(或更新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执行测试(如果需要,使用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源文件一样,您可以移动测试源文件。只需更新gradle sourceSets
配置。
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
androidTest {
setRoot('tests')
}
}
您忘记在应用构建脚本中添加junit测试依赖项
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile 'org.robolectric:robolectric:2.3'
androidTestCompile 'junit:junit:4.10'
}
您正在使用Android Studio中的运行配置而不是命令行(Android Studio中的终端选项卡)运行此测试。要从Android Studio运行它,您必须更新app.iml
文件以在底部列出jdk条目。有关详细信息,请参阅deckard-gradle example。
完整的错误示例:
!!! 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)
有关解决方案,请参阅this 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/
我发现的最好的文章是:
答案 2 :(得分:22)
从Android Studio 1.1开始,答案很简单: http://tools.android.com/tech-docs/unit-testing-support
答案 3 :(得分:4)
现在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
答案 4 :(得分:1)
Android Studio 1.2 + 为 JUnit设置项目非常简单尝试按照本教程进行操作:
这是为JUnit设置项目最简单的部分:
https://io2015codelabs.appspot.com/codelabs/android-studio-testing#1
按照过去的链接,直到“Running your tests”
现在,如果你想与intrumentation测试集成,请从这里开始:
https://io2015codelabs.appspot.com/codelabs/android-studio-testing#6
答案 5 :(得分:0)
请参阅Android开发者官方网站上的tutorial。本文还介绍了如何为测试创建模型。
顺便说一句,你应该注意到简单JUnit测试的依赖关系的范围应该是&#34; testCompile&#34;。