29 votes

Robolectric avec Gradle : Ressources non trouvées

J'essaie d'exécuter mes tests Robolectric avec le nouveau système de construction Android Gradle, mais je suis bloqué au niveau de l'accès aux ressources de mon projet principal.

J'ai divisé la construction en deux projets distincts pour éviter les conflits entre le java y el android gradle, de sorte que la structure du répertoire ressemble à peu près à ceci :

.
├── build.gradle
├── settings.gradle
├── mainproject
│   ├── build
│   │   ├── classes
│   │   │   └── debug
│   ├── build.gradle
│   └── src
│       └── main
│           ├── AndroidManifest.xml
│           └── ...
└── test
    ├── build.gradle
    └── src
        └── test
            └── java
                └── ...
                    └── test
                        ├── MainActivityTest.java
                        ├── Runner.java
                        ├── ServerTestCase.java
                        └── StatusFetcherTest.java

Mi build.gradle en test/ ressemble actuellement à ceci :

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.stanfy.android:gradle-plugin-java-robolectric:2.0'
    }
}

apply plugin: 'java-robolectric'

repositories {...}

javarob {
    packageName = 'com.example.mainproject'
}

test {
    dependsOn ':mainproject:build'
    scanForTestClasses = false
    include "**/*Test.class"
    // Oh, the humanity!
    def srcDir = project(':mainproject').android.sourceSets.main.java.srcDirs.toArray()[0].getAbsolutePath()
    workingDir srcDir.substring(0, srcDir.lastIndexOf('/'))
}

project(':mainproject').android.sourceSets.main.java.srcDirs.each {dir ->
    def buildDir = dir.getAbsolutePath().split('/')
    buildDir =  (buildDir[0..(buildDir.length - 4)] + ['build', 'classes', 'debug']).join('/')

    sourceSets.test.compileClasspath += files(buildDir)
    sourceSets.test.runtimeClasspath += files(buildDir)
}

dependencies {    
    testCompile group: 'com.google.android', name: 'android', version: '4.1.1.4'
    testCompile group: 'org.robolectric', name: 'robolectric', version: '2.0-alpha-3'
    ...
}

Le piratage diabolique du classpath me permet d'accéder à toutes les classes de mon projet principal, à l'exception de R qui existe en tant que .class dans le répertoire de construction, mais soulève cette erreur lors de l'exécution de l'opération. compileTestJava tâche :

/.../MainActivityTest.java:16: error: cannot find symbol
                final String appName = activity.getResources().getString(R.string.app_name);
                                                                          ^
  symbol:   variable string
  location: class R
1 error
:test:compileTestJava FAILED

Il doit y avoir une meilleure façon d'exécuter les tests Robolectric avec le nouveau système de construction, non ?

( Source complète de l'application )

27voto

user2457888 Points 276

J'ai rencontré le même problème et voici ce que j'ai trouvé. Au lieu de créer un projet séparé pour les tests, j'ai créé un ensemble de sources pour les tests Robolectric et ajouté une nouvelle tâche dont "check" dépendrait. En utilisant une partie du code de votre question, voici les éléments pertinents du fichier de construction (fonctionnel) :

apply plugin: 'android'

sourceSets {
    testLocal {
        java.srcDir file('src/test/java')
        resources.srcDir file('src/test/resources')
    }
}

dependencies {
    compile 'org.roboguice:roboguice:2.0'
    compile 'com.google.android:support-v4:r6'

    testLocalCompile 'junit:junit:4.8.2'
    testLocalCompile 'org.robolectric:robolectric:2.1'
    testLocalCompile 'com.google.android:android:4.0.1.2'
    testLocalCompile 'com.google.android:support-v4:r6'
    testLocalCompile 'org.roboguice:roboguice:2.0'
}

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

J'ai inclus mon bloc de dépendances pour signaler que, pour que je puisse le mettre en place, j'ai dû répéter tous les éléments de mon système de gestion de l'information. compile dans mon système personnalisé testLocal l'ensemble des sources.

Running gradle testLocal construit et exécute uniquement les tests à l'intérieur de src/test/java en cours d'exécution gradle check exécute ces tests en plus de ceux du jeu de sources Android instrumentTest par défaut.

J'espère que cela vous aidera !

8voto

Saad Farooq Points 2507

Mise à jour : Jake Wharton vient d'annoncer le gradle-android-test-plugin . Vous pouvez le trouver à l'adresse suivante https://github.com/square/gradle-Android-test-plugin

Cela semble être assez simple, surtout si vous prévoyez d'utiliser robolectric .


Ancienne réponse ci-dessous

El robolectric-plugin semble prometteur.

L'échantillon build.gradle Le fichier qu'ils fournissent est :

buildscript {
    repositories {
        mavenCentral()
        maven {
            url "https://oss.sonatype.org/content/repositories/snapshots"
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4.2'
        classpath 'com.novoda.gradle:robolectric-plugin:0.0.1-SNAPSHOT'
    }
}

apply plugin: 'android'
apply plugin: 'robolectric'

repositories {
    mavenCentral()
    mavenLocal()
    maven {
        url "https://oss.sonatype.org/content/repositories/snapshots"
    }
}

dependencies {
    //compile files('libs/android-support-v4.jar')

    // had to deploy to sonatype to get AAR to work
    compile 'com.novoda:actionbarsherlock:4.3.2-SNAPSHOT'

    robolectricCompile 'org.robolectric:robolectric:2.0'
    robolectricCompile group: 'junit', name: 'junit', version: '4.+'
}

android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 17
    }
}

Il ne semble pas fonctionner avec le plugin Android Gradle version 0.5 mais peut-être le fera-t-il bientôt.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X