webentwicklung-frage-antwort-db.com.de

Ausführen einfacher JUnit-Tests unter Android Studio (IntelliJ) bei Verwendung einer Gradle-basierten Konfiguration

Ich verwende Android Studio/IntelliJ, um auf einem vorhandenen Android-Projekt aufzubauen, und möchte einige einfache JUnit-Komponententests hinzufügen. Was ist der richtige Ordner, um solche Tests hinzuzufügen?

Das Android-Plugin Gradle definiert eine Verzeichnisstruktur mit src/main/Java für den Hauptquellcode und src/instrumentTest/Java für Android-Tests. 

Der Versuch, meine JUnit-Tests in instrumentTest hinzuzufügen, hat für mich nicht funktioniert. Ich kann es als Android-Test ausführen (dafür scheint dieses Verzeichnis zu sein), aber das ist nicht das, wonach ich suche - ich möchte nur einen einfachen JUnit-Test ..__ ausführen das hat auch nicht funktioniert - ich nehme an, ich verwende ein Verzeichnis, das als Android Test anstelle von Source gekennzeichnet ist.

Wenn ich einen neuen Quellordner anlege und als solcher in der Projektstruktur markiere, wird dies beim nächsten Mal gelöscht, wenn IntelliJ die Projektkonfiguration aus den Gradle-Build-Dateien aktualisiert.

Was ist der geeignetere Weg, um JUnit-Tests in einem gradbasierten Android-Projekt unter IntelliJ zu konfigurieren? Welche Verzeichnisstruktur soll dafür verwendet werden?

78
Julian Cerruti

Ab Android Studio 1.1 ist die Antwort jetzt einfach: http://tools.Android.com/tech-docs/unit-testing-support

22
Erik B

Normalerweise kannst du nicht. Willkommen in der Welt von Android, wo alle Tests auf einem Gerät ausgeführt werden müssen (außer Robolectric).

Der Hauptgrund ist, dass Sie nicht wirklich über die Quellen des Frameworks verfügen. Selbst wenn Sie die IDE davon überzeugen, den Test lokal auszuführen, erhalten Sie sofort die Ausnahme "Stub! Nicht implementiert" Warum? " du fragst dich vielleicht? Da der Android.jar, den Ihnen das SDK gibt, tatsächlich alle entfernt ist - alle Klassen und Methoden sind vorhanden, werfen jedoch nur eine Ausnahme aus. Es ist dazu da, eine API bereitzustellen, aber nicht, um Ihnen eine tatsächliche Implementierung zu geben.

Es gibt ein wunderbares Projekt namens Robolectric , das einen Großteil des Frameworks implementiert, sodass Sie aussagekräftige Tests durchführen können. In Verbindung mit einem guten Mock-Framework (z. B. Mockito) wird Ihr Job überschaubar.

Gradle Plugin: https://github.com/robolectric/robolectric-gradle-plugin

36
Delyan

Intro

Beachten Sie, dass robolectric 2.4 zum Zeitpunkt des Schreibens die neueste Version ist und keine Unterstützung für die appcompat v7-Bibliothek bietet. Unterstützung wird in Version 3.0 von robolectric hinzugefügt (noch keine ETA). Auch ActionBar Sherlock kann Probleme mit Robolectric verursachen.

Um Robolectric in Android Studio verwenden zu können, haben Sie zwei Möglichkeiten:

(Option 1) - Ausführen von JUnit-Tests mit Android Studio mit einem Java-Modul

Diese Technik verwendet ein Java-Modul für alle Ihre Tests mit einer Abhängigkeit zu Ihrem Android-Modul und einen benutzerdefinierten Testläufer mit etwas Magie:

Anweisungen finden Sie hier: http://blog.blundellapps.com/how-to-run-robolectric-junit-tests-in-Android-studio/

Überprüfen Sie auch den Link am Ende dieses Beitrags, um die Tests von Android Studio aus durchzuführen.

(Option 2) - Ausführen von JUnit-Tests mit Android Studio unter Verwendung von robolectric-gradle-plugin

Ich habe ein paar Probleme mit der Einrichtung von Junit-Tests zur Ausführung von Absolventen in Android Studio festgestellt.

Dies ist ein sehr einfaches Beispielprojekt zum Ausführen von Junit-Tests eines gradle-basierten Projekts in Android Studio: https://github.com/hanscappelle/Android-studio-junit-robolectric Dies wurde mit Android Studio 0.8.14 getestet , JUnit 4.10, robolectric gradle plugin 0.13+ und robolectric 2.3 

Buildscript (Projekt/Build.gradle)

Das Build-Skript ist die Datei build.gradle im Stammverzeichnis Ihres Projekts. Dort musste ich robolectric gradle plugin zu classpath hinzufügen

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

Projekt-Buildscript (App/build.gradle)

Verwenden Sie im Build-Skript Ihres App-Moduls das Plugin robolectric, fügen Sie robolectric config hinzu und fügen Sie androidTestCompile-Abhängigkeiten hinzu.

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

Erstellen Sie JUnit-Testklassen

Legen Sie die Testklassen jetzt in den Standardspeicherort (oder aktualisieren Sie die Gradle-Konfiguration). 

app/src/androidTest/Java

Benennen Sie Ihre Testklassen mit "Test" (oder aktualisieren Sie erneut "config"), erweitern Sie junit.framework.TestCase und kommentieren Sie Testmethoden mit "@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;
    }
}

Tests ausführen

Führen Sie dann die Tests mit gradlew von der Kommandozeile aus (machen Sie sie ggf. mit chmod +x ausführbar).

./gradlew clean test

Beispielausgabe:

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

Fehlerbehebung

alternative Quellverzeichnisse

So wie Sie Ihre Java-Quelldateien an einem anderen Ort haben können, können Sie auch Ihre Testquelldateien verschieben. Aktualisieren Sie einfach gradle sourceSets config.

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

        androidTest {
            setRoot('tests')
        }
    }

das Paket org.junit ist nicht vorhanden

Sie haben vergessen, die Junit-Testabhängigkeit im App-Buildskript hinzuzufügen

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

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

Java.lang.RuntimeException: Stub!

Sie führen diesen Test mit den Laufkonfigurationen von Android Studio anstelle der Befehlszeile aus (Registerkarte "Terminal" in Android Studio). Um es von Android Studio aus auszuführen, müssen Sie die app.iml-Datei aktualisieren, damit der Eintrag jdk unten angezeigt wird. Siehe Deckard-Gradle-Beispiel für Details.

Vollständiges Fehlerbeispiel: 

!!! 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)

FEHLER: Java_HOME ist auf ein ungültiges Verzeichnis gesetzt

Siehe diese SO Frage für eine Lösung. Fügen Sie den folgenden Export zu Ihrem Bash-Profil hinzu:

export Java_HOME=`/usr/libexec/Java_home -v 1.7`  

Das vollständige Fehlerprotokoll:

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.

Testklasse nicht gefunden

Wenn Sie Ihre Tests stattdessen mit Android Studio Junit Test Runner ausführen möchten, müssen Sie die build.gradle-Datei ein wenig erweitern, damit Android Studio Ihre kompilierten Testklassen finden kann:

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

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

Einige weitere Ressourcen

Die besten Artikel, die ich dazu gefunden habe, sind:

32
hcpl

Dies wird jetzt in Android Studio unterstützt, beginnend mit dem Android Gradle Plugin 1.1.0.

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

Beispiel-App mit lokalen Unit-Tests auf GitHub:

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

4

Für Android Studio 1.2+ ist das Einrichten eines Projekts für JUnit ziemlich einfach. Versuchen Sie, diesem Tutorial zu folgen:

Dies ist der einfachste Teil, um ein Projekt für JUnit einzurichten:

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

Folgen Sie dem vorherigen Link bis " Ausführen Ihrer Tests "

Wenn Sie nun den Instrumententest integrieren möchten, folgen Sie hier: 

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

1
CommonSenseCode

Bitte sehen Sie dieses Tutorial auf der offiziellen Website von Android Developers. In diesem Artikel wird auch beschrieben, wie Sie Modelle für Ihre Tests erstellen.

Sie sollten übrigens beachten, dass der Umfang der Abhängigkeiten für den einfachen JUnit-Test "testCompile" sein sollte.

0
BlueMice