79

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

AndroidGradleプラグインはsrc/main/java、メイン ソース コードとテストsrc/instrumentTest/java用のディレクトリ構造を定義します。Android

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

新しいソース フォルダーを作成し、プロジェクト構造でそのようにマークすると、次回 gradleIntelliJビルド ファイルからプロジェクト構成を更新するときに消去されます。

上の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 テストを実行する

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

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

また、その投稿の最後にあるリンクをチェックして、Android Studio からテストを実行してください。

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

Android Studio で gradle から実行するように junit テストを設定する際に、いくつかの問題が発生しました。

これは、 Android Studio で gradleベースのプロジェクトから junit テストを実行するための非常に基本的なサンプル プロジェクトです: https://github.com/hanscapelle/android-studio-junit-robolectric robolectric gradle プラグイン 0.13+ および robolectric 2.3

ビルドスクリプト (project/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;
    }
}

テストの実行

次に、コマンドラインから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 sourceSetsconfigを更新するだけです。

    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 エントリがリストされるようにする必要があります。詳細については、 deccard-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 の質問を参照してください。以下のエクスポートを 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 からテストを実行する場合は、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

から: 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 に答える
0

Android Developers 公式サイトからこのチュートリアルを参照してください。この記事では、テスト用のモックアップを作成する方法も示します。

ちなみに、単純な JUnit テストの依存関係のスコープは「testCompile」にする必要があることに注意してください。

于 2015-12-09T01:36:06.410 に答える