web-dev-qa-db-ja.com

Gradleベースの構成を使用する場合、Android St​​udio(IntelliJ)で簡単なJUnitテストを実行する

Android Studio/IntelliJを使用して既存のAndroidプロジェクトをビルドしており、簡単なJUnit単体テストを追加したいと思います。そのようなテストを追加する適切なフォルダーは何ですか?

Android Gradleプラグインは、メインソースコードにsrc/main/JavaAndroidテストにsrc/instrumentTest/Javaを使用してディレクトリ構造を定義します。

InstrumentTestにJUnitテストを追加しようとしてもうまくいきませんでした。 Androidテストとして実行できます(そのディレクトリの目的です)が、それは私が探しているものではありません-単純なJUnitテストを実行したいだけです。このクラスのJUnit実行構成を作成しようとしましたが、それも機能しませんでした。ソースではなくAndroid Testというフラグが付けられたディレクトリを使用しているためだと思います。

新しいソースフォルダーを作成し、Project Structureでそのようにマークすると、次回IntelliJがgradleビルドファイルからプロジェクト構成を更新します。

IntelliJのgradleベースのAndroidプロジェクトでJUnitテストを構成するより適切な方法は何ですか?これに使用するディレクトリ構造はどれですか?

78
Julian Cerruti

Android St​​udio 1.1以降、答えは簡単になりました。 http://tools.Android.com/tech-docs/unit-testing-support

22
Erik B

通常はできません。 Androidの世界へようこそ。Androidでは、すべてのテストをデバイスで実行する必要があります(Robolectricを除く)。

主な理由は、実際にフレームワークのソースを持っていないためです。IDEをテストしてローカルで実行するように説得しても、すぐに「スタブ!実装されていません」例外が発生します。 "なぜ?"あなたは疑問に思うかもしれません? SDKが提供するAndroid.jarは実際にはすべてスタブ化されているためです。すべてのクラスとメソッドはありますが、例外をスローするだけです。 APIを提供するためのものですが、実際の実装を提供するためのものではありません。

Robolectric と呼ばれるすばらしいプロジェクトがあります。これは、意味のあるテストを実行できるように多くのフレームワークを実装しています。優れたモックフレームワーク(Mockitoなど)と組み合わせると、ジョブを管理しやすくなります。

Gradleプラグイン: https://github.com/robolectric/robolectric-gradle-plugin

36
Delyan

イントロ

執筆時点では、robolectric 2.4は最新バージョンであり、appcompat v7ライブラリをサポートしていないことに注意してください。 robolectric 3.0リリースでサポートが追加されます(ETAはまだありません)。また、ActionBar Sherlockは、robolectricで問題を引き起こす可能性があります。

Android St​​udio内でRobolectricを使用するには、2つのオプションがあります。

(オプション1)-Androidモジュールを使用してJava St​​udioでJUnitテストを実行する

この手法では、Javaモジュールに依存するすべてのテストにAndroidモジュールを使用し、カスタムテストランナーにいくつかの魔法を使用します。

手順はここにあります: http://blog.blundellapps.com/how-to-run-robolectric-junit-tests-in-Android-studio/

また、Android studioからテストを実行するために、その投稿の最後にあるリンクを確認してください。

(オプション2)-robolectric-gradle-pluginを使用してAndroid St​​udioでJUnitテストを実行する

Android St​​udioのgradleから実行するようにju​​nitテストを設定する際にいくつかの問題が発生しました。

これは、Android St​​udioのgradleベースのプロジェクトからjunitテストを実行するための非常に基本的なサンプルプロジェクトです。 https://github.com/hanscappelle/Android-studio-junit-robolectric これは、Android St​​udio 0.8.14、JUnit 4.10、robolectric gradle plugin 0.13+およびrobolectric 2.3でテストされました

Buildscript(project/build.gradle)

ビルドスクリプトは、プロジェクトのルートにあるbuild.gradleファイルです。そこで robolectric gradle plugin をクラスパスに追加する必要がありました

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()
    }
}

プロジェクトbuildscript(App/build.gradle)

アプリモジュールのビルドスクリプトで、robolectricプラグインを使用して、robolectric configを追加し、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 configを更新します)

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 configを更新するだけです。

    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 St​​udioの[ターミナル]タブ)ではなく、Android St​​udioからの実行構成でこのテストを実行しています。 Android St​​udioから実行するには、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が無効なディレクトリに設定されています

解決策については 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 St​​udio Junitテストランナーからテストを実行する場合、Android studioがコンパイル済みのテストクラスを見つけることができるように、build.gradleファイルをもう少し拡張する必要があります。 :

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

from: http://kostyay.name/Android-studio-robolectric-gradle-getting-work/

その他のリソース

これについて私が見つけた最高の記事は次のとおりです。

32
hcpl

これはAndroid Gradleプラグイン1.1.0以降のAndroid St​​udioでサポートされるようになりました。これをチェックしてください:

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

GitHubのローカルユニットテストを使用したサンプルアプリ:

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

4

Android Studio 1.2 +の場合、JUnitのプロジェクトを設定するのは非常に簡単ですこのチュートリアルに従ってください:

これは、JUnitのプロジェクトを設定する最も簡単な部分です。

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

テストの実行 」まで、過去のリンクをたどります

ここで、インストルメンテーションテストと統合する場合は、次の手順に従ってください。

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

1
CommonSenseCode

これをご覧ください tutorial Android Developers公式サイトから。この記事では、テスト用のモックアップを作成する方法も示します。

ところで、単純なJUnitテストの依存関係の範囲は "testCompile"であることに注意してください。

0
BlueMice