web-dev-qa-db-fra.com

Robolectric avec Gradle: Ressources non trouvées

J'essaie d'exécuter mes tests Robolectric avec le nouveau système de génération Gradle Android, mais je suis coincé à accéder aux ressources de mon projet principal.

J'ai divisé la construction en deux projets distincts pour éviter les conflits entre les plugins Java et 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

Ma build.gradle dans 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 evil classpath me permet d'accéder à toutes les classes de mon projet principal, à l'exception de R, qui existe sous la forme .class fichier dans le répertoire de génération, mais déclenche cette erreur lors de la tâche compileTestJava:

/.../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 des tests Robolectric avec le nouveau système de construction, non?

( Source complète de l'application )

31
passy

Je rencontrais ce même problème et c'est ce que j'ai trouvé. Au lieu de créer un projet séparé pour les tests, j'ai créé un ensemble source pour les tests Robolectric et ajouté une nouvelle tâche dont "vérifier" dépendrait. En utilisant une partie du code de votre question, voici les bits pertinents du fichier de construction (de travail):

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 souligner que pour que cela soit opérationnel, j'ai dû répéter toutes mes dépendances compile dans mon ensemble source personnalisé testLocal.

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

J'espère que cela t'aides!

27
user2457888

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

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


Ancienne réponse ci-dessous

Le 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 Android plugin Gradle version 0.5 mais peut-être que ce sera bientôt.

8
Saad Farooq