web-dev-qa-db-fra.com

Exécution de tests JUnit simples sur Android Studio (IntelliJ) lors de l'utilisation d'une configuration basée sur Gradle

J'utilise Android Studio/IntelliJ pour créer un projet Android existant et souhaite ajouter quelques tests unitaires JUnit simples. Quel est le bon dossier pour ajouter de tels tests?

Le plug-in Gradle sous Android définit une structure de répertoire avec src/main/Java pour le code source principal et src/instrumentTest/Java pour les tests Android

Essayer d'ajouter mes tests JUnit dans instrumentTest n'a pas fonctionné pour moi. Je peux l'exécuter comme un test Android (c'est ce que ce répertoire semble avoir) mais ce n'est pas ce que je recherche - je veux juste exécuter un simple test JUnit . J'ai essayé de créer une configuration d'exécution JUnit pour cette classe, mais cela n'a pas fonctionné non plus - je suppose parce que j'utilise un répertoire qui est marqué comme Android Test au lieu de Source.

Si je crée un nouveau dossier source et le marque en tant que tel dans la structure du projet, celui-ci sera effacé lors de la prochaine régénération IntelliJ de la configuration du projet à partir des fichiers de construction de dégradés.

Quel est le moyen le plus approprié de configurer des tests JUnit dans un projet Android basé sur des graduations sur IntelliJ? Quelle structure de répertoire utiliser pour cela?

78
Julian Cerruti

Depuis Android Studio 1.1, la réponse est désormais simple: http://tools.Android.com/tech-docs/unit-testing-support

22
Erik B

Normalement, vous ne pouvez pas. Bienvenue dans le monde d'Android, où tous les tests doivent être exécutés sur un appareil (sauf Robolectric).

La raison principale est que vous n'avez pas réellement les sources du framework - même si vous convaincez IDE d'exécuter le test localement, vous obtiendrez immédiatement une exception "Stub! Not Implement" . "Pourquoi? " vous pourriez vous demander? Parce que le Android.jar que le SDK vous donne est en réalité tout écrasé - toutes les classes et méthodes sont là mais elles jettent toutes une exception. Il est là pour fournir une API mais pas pour vous donner une implémentation réelle.

Il existe un projet merveilleux appelé Robolectric qui implémente une grande partie de la structure afin que vous puissiez exécuter des tests significatifs. Couplé à un bon cadre factice (par exemple, Mockito), il rend votre travail gérable.

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

36
Delyan

Intro

Notez qu'au moment de la rédaction de ce document, Robolectric 2.4 était la dernière version et ne prend pas en charge la bibliothèque appcompat v7. Un support sera ajouté à la version robolectric 3.0 (pas encore d’ETA). De plus, ActionBar Sherlock peut causer des problèmes avec robolectric.

Pour utiliser Robolectric dans Android Studio, vous avez 2 options:

(Option 1) - Exécution de tests JUnit avec Android Studio à l'aide d'un module Java

Cette technique utilise un module Java pour tous vos tests avec une dépendance à votre module Android et un programme d'exécution de test personnalisé avec une certaine magie:

Les instructions peuvent être trouvées ici: http://blog.blundellapps.com/how-to-run-robolectric-junit-tests-in-Android-studio/

Vérifiez également le lien à la fin de ce message pour l'exécution des tests à partir du studio Android.

(Option 2) - Exécution de tests JUnit avec Android Studio à l'aide de robolectric-gradle-plugin

J'ai rencontré quelques problèmes lors de la configuration des tests Junit pour qu'ils s'exécutent graduellement dans Android Studio.

Il s'agit d'un exemple de projet très basique permettant d'exécuter des tests junit à partir d'un projet basé sur plusieurs versions d'Android Studio: https://github.com/hanscappelle/Android-studio-junit-robolectric Ceci a été testé avec Android Studio 0.8.14 , JUnit 4.10, plugin robolectric gradle 0.13+ et robolectric 2.3 

Buildscript (project/build.gradle)

Le script de construction est le fichier build.gradle situé à la racine du projet. Là je devais ajouter plugin robolectric gradle à 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()
    }
}

Buildscript du projet (App/build.gradle)

Dans le script de construction de votre module d'application, utilisez le plugin robolectric, ajoutez robolectric config et ajoutez les dépendances 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'
}

Créer des classes de test JUnit

Placez maintenant les classes de test à l’emplacement par défaut (ou mettez à jour config gradle) 

app/src/androidTest/Java

Et nommez vos classes de tests se terminant par Test (ou encore mettez à jour config), en étendant junit.framework.TestCase et annotez les méthodes de test avec @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;
    }
}

Exécuter des tests

Ensuite, exécutez les tests en utilisant gradlew à partir de la ligne de commande (rendez-le exécutable en utilisant chmod +x si nécessaire)

./gradlew clean test

Exemple de sortie:

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

Dépannage

répertoires sources alternatifs

Tout comme vous pouvez avoir vos fichiers source Java ailleurs, vous pouvez déplacer vos fichiers source de test. Il suffit de mettre à jour gradle sourceSets config.

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

        androidTest {
            setRoot('tests')
        }
    }

le paquet org.junit n'existe pas

Vous avez oublié d'ajouter la dépendance du test Junit dans le script de construction de l'application.

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

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

Java.lang.RuntimeException: Stub!

Vous exécutez ce test avec les configurations d'exécution d'Android Studio au lieu de la ligne de commande (onglet Terminal dans Android Studio). Pour l'exécuter à partir d'Android Studio, vous devez mettre à jour le fichier app.iml pour que l'entrée jdk soit répertoriée en bas. Voir exemple de deckard-gradle pour plus de détails.

Exemple d'erreur complet: 

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

ERREUR: Java_HOME est défini sur un répertoire non valide.

Voir cette SO question pour une solution. Ajoutez l'export ci-dessous à votre profil bash:

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

Le journal des erreurs complet:

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.

Classe de test non trouvée

Si vous souhaitez exécuter vos tests à partir d'Android Studio Junit Test Runner, vous devrez développer un peu plus le fichier build.gradle afin qu'Android Studio puisse trouver vos classes de tests compilées:

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

à partir de: http://kostyay.name/Android-studio-robolectric-gradle-getting-work/

Quelques ressources supplémentaires

Les meilleurs articles que j'ai trouvés autour de ça sont:

32
hcpl

Ceci est maintenant supporté dans Android Studio à partir du plugin Android Gradle 1.1.0, regardez ceci:

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

Exemple d'application avec des tests unitaires locaux sur GitHub:

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

4
Lorenzo Polidori

Pour Android Studio 1.2+, configurer un projet pour JUnit est assez simple essayez de suivre ce tutoriel:

C’est la partie la plus simple de la configuration d’un projet pour JUnit:

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

Suivez le lien précédent jusqu'à " Exécuter vos tests "

Maintenant, si vous souhaitez intégrer un test d'intrumentation, suivez-nous à partir d'ici: 

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

1
CommonSenseCode

S'il vous plaît voir ce tutoriel du site officiel des développeurs Android. Cet article explique également comment créer des maquettes pour vos tests.

A propos, notez que la portée des dépendances pour le test JUnit simple devrait être "testCompile".

0
BlueMice