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 développer un projet Android existant et je voudrais append quelques tests unitaires JUnit simples. Quel est le bon dossier pour append de tels tests?

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

Essayer d’append mes tests JUnit dans instrumentTest ne fonctionnait pas pour moi. Je peux l’exécuter comme un test Android (c’est ce que ce répertoire semble être) mais ce n’est pas ce que je cherche – je veux juste lancer 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é. Je suppose que j’utilise un répertoire marqué comme test Android au lieu de Source.

Si je crée un nouveau dossier source et le marque comme tel dans Structure de projet, cela sera effacé la prochaine fois IntelliJ actualisera la configuration du projet à partir des fichiers de construction graduelle.

Quelle est la manière la plus appropriée de configurer les tests JUnit dans un projet Android basé sur IntelliJ sur IntelliJ ? Quelle structure de répertoire utiliser pour cela?

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

Normalement, vous ne pouvez pas. Bienvenue dans le monde d’Android, où tous les tests doivent être exécutés sur un périphérique (sauf Robolecsortingc).

La raison principale est que vous n’avez pas réellement les sources du framework – même si vous convaincez l’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 fait complètement supprimé – toutes les classes et les méthodes sont là mais elles ne font que lancer une exception. Il est là pour fournir une API mais pas pour vous fournir une implémentation réelle.

Il y a un projet merveilleux appelé Robolecsortingc qui implémente une grande partie du framework pour que vous puissiez exécuter des tests significatifs. Associé à un bon cadre de simulation (par exemple, Mockito), votre travail est gérable.

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

Introduction

Notez qu’au moment de l’écriture, robolecsortingc 2.4 est la dernière version et ne prend pas en charge la bibliothèque appcompat v7 . Le support sera ajouté dans la version 3.0 de Robolecsortingc ( pas d’ETA ). Aussi ActionBar Sherlock peut causer des problèmes avec la robotique.

Pour utiliser Robolecsortingc dans Android Studio, vous avez deux options:

(Option 1) – Exécution des 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 testeur personnalisé avec un peu de magie:

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

Vérifiez également le lien à la fin de cet article pour exécuter les tests du studio Android.

(Option 2) – Exécution des tests JUnit avec Android Studio en utilisant robolecsortingc-gradle-plugin

J’ai rencontré quelques problèmes lors de la configuration des tests de Junit à exécuter depuis Gradle dans Android Studio.

Ceci est un exemple de projet très basique pour exécuter des tests Junit à partir d’un projet basé sur des gradients dans Android Studio: https://github.com/hanscappelle/android-studio-junit-robolecsortingc Ceci a été testé avec Android Studio 0.8.14, JUnit 4.10, plugin robotique 0.13+ et robolecsortingc 2.3

Buildscript (project / build.gradle)

Le script de génération est le fichier build.gradle à la racine de votre projet. Là, je devais append un plugin de gradation robotique à 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.robolecsortingc:robolecsortingc-gradle-plugin:0.13.+' } } allprojects { repositories { jcenter() } } 

Script de projet (App / build.gradle)

Dans le script de génération de votre module d’application, utilisez le plugin robolecsortingc , ajoutez la configuration de robolecsortingc et ajoutez les dépendances androidTestComstack .

 apply plugin: 'com.android.application' apply plugin: 'robolecsortingc' android { // like any other project } robolecsortingc { // 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 { comstack fileTree(dir: 'libs', include: ['*.jar']) androidTestComstack 'org.robolecsortingc:robolecsortingc:2.3' androidTestComstack 'junit:junit:4.10' } 

Créer des classes de test JUnit

Maintenant, placez les classes de test dans l’emplacement par défaut (ou mettez à jour graduellement la configuration)

 app/src/androidTest/java 

Et nommez vos classes de tests en terminant par Test (ou encore mettez à jour la configuration), en étendant junit.framework.TestCase et en annotant 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 

Sortie de l’échantillon:

 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 sources de test. Il suffit de mettre à jour la configuration de sourceSets sourceSets .

  sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } androidTest { setRoot('tests') } } 

Le package org.junit n’existe pas

Vous avez oublié d’append la dépendance au test de Junit dans le script de génération de l’application

 dependencies { comstack fileTree(dir: 'libs', include: ['*.jar']) androidTestComstack 'org.robolecsortingc:robolecsortingc:2.3' androidTestComstack '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.(BaseTestRunner.java:5) at junit.textui.TestRunner.(TestRunner.java:54) at junit.textui.TestRunner.(TestRunner.java:48) at junit.textui.TestRunner.(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 question SO 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 voulez exécuter vos tests à partir du runner Android Studio Junit Test, vous devrez développer le fichier build.gradle un peu plus pour que Android Studio puisse trouver vos classes de test 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 testLocalComstack 'junit:junit:4.11' testLocalComstack 'com.google.android:android:4.1.1.4' testLocalComstack 'org.robolecsortingc:robolecsortingc: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 androidTestComstack 'junit:junit:4.11' androidTestComstack 'com.google.android:android:4.1.1.4' androidTestComstack 'org.robolecsortingc:robolecsortingc: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.comstackClasspath += files(buildDir) sourceSets.testLocal.runtimeClasspath += files(buildDir) } classpath = sourceSets.testLocal.runtimeClasspath } check.dependsOn localTest 

de: http://kostyay.name/android-studio-robolecsortingc-gradle-getting-work/

Quelques ressources supplémentaires

Les meilleurs articles que j’ai trouvés autour de ceci sont:

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 tests unitaires locaux sur GitHub:

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

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 mise en place d’un projet pour JUnit:

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

Suivez le lien précédent jusqu’à ce que ” Lancer vos tests ”

Maintenant, si vous souhaitez intégrer le test d’intrumentation, procédez comme suit:

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

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

Au fait, vous devriez noter que la scope des dépendances pour un test JUnit simple devrait être “testComstack”.