2013-05-20 9 views
30

Я пытаюсь запустить свои тесты Robolectric вместе с новой системой сборки Gradle Android, но я застрял в доступе к ресурсам моего основного проекта.Robolectric with Gradle: Ресурсы не найдены

Я разделил сборку на два отдельных проектов, чтобы избежать конфликтов между java и android Gradle плагинов, поэтому структура каталогов выглядит примерно так:

. 
├── 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 

Мои build.gradle в test/ в настоящее время выглядит следующим образом:

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

зло повозки, запряженные волы позволяют классам мне получить доступ ко всем классам моего основного проекта, за исключением R, который существует как .class файла в каталоге сборки, но вызывает эту ошибку во время 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 

Там должен быть лучшим способом выполнить Robolectric тестов с новой системой построения, не так ли?

(Full source of the app)

+2

Я не думаю, что это сработает.В robolectric есть еще кое-что из того, где найти фактические ресурсы, которые не будут работать (или масштабировать для проектов с зависимостями) с тем, что делает плагин gradle. Мне нужно работать с разработчиками Robolectric, чтобы сделать его совместимым. Это в моем списке вещей. –

+0

Спасибо за ввод, @Xav. – passy

+0

Итак, есть ли еще способ запустить robolectric с градиентом в новой идее Android Studio? – Imanol

ответ

27

я бегала по этому же вопросу, и это то, что я придумал. Вместо создания отдельного проекта для тестов я создал исходный набор для тестов Robolectric и добавил новую задачу, от которой зависело бы «проверка». Используя часть кода из вашего вопроса, вот соответствующие биты (рабочего) построить файл:

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 

Я включил мои зависимости блок, чтобы указать на то, что для того, чтобы мне получить это и происходит , Мне пришлось повторить все мои зависимости compile в моем настраиваемом наборе testLocal.

Запуск gradle testLocal строит и запускает только тесты внутри src/test/java, в то время как работающий gradle check выполняет эти тесты в дополнение к тем, которые установлены в исходном наборе инструментов Android.

Надеюсь, это поможет!

+0

Это выглядит как огромный шаг в правильном направлении, спасибо! Тем не менее, Robolectric testrunner выполняет «android.content.res.Resources $ NotFoundException: неизвестный ресурс xxx», когда что-либо пытается получить доступ к ресурсу. Полный stacktrace здесь: https://gist.github.com/passy/255bbd42ada11ad5fba7 – passy

+1

Кажется, что у испытуемого не получается найти «AndroidManifest.xml», который находится в 'src/main'. Думаю, я мог бы установить эти пути в подклассе RobolectricTestRunner, но с Eclipse я бы просто установил рабочий каталог в основной проект. Могу ли я сделать это в файле gradle? – passy

+1

@passy К сожалению, я не видел, чтобы эта проблема возникла. Тем не менее, вы должны поместить свой 'AndroidManifest.xml' в корень каталога проекта и переопределить исходный набор манифеста, выполнив что-то подобное в' build.gradle': 'android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml'}}} 'Источник: http://tools.android.com/tech-docs/new-build-system/user-guide – user2457888

8

Обновление: Jake Wharton только что анонсировал gradle-android-test-plugin. Вы можете найти его на https://github.com/square/gradle-android-test-plugin

Это кажется довольно обтекаемым, особенно если вы планируете использовать robolectric.


Старый Ответ Ниже

robolectric-plugin выглядит многообещающим.

Пример файла build.gradle они обеспечивают:

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

Это не похоже на работу с Android Gradle плагин версии 0.5, но, возможно, это будет в ближайшее время.

+0

Я с нетерпением жду плагина Джейка для поддержки ресурсов, разделенных buildType. В настоящее время, похоже, это не так.Кто-то написал патч, чтобы исправить это (несколько месяцев назад), но комментариев к нему не было и он не был принят. До тех пор, метод в принятом ответе работает. –

+2

Кажется, что плагин Джейка Уортона теперь устарел? – Flame

+0

Да, это так. Кажется, есть шквал, чтобы перейти к стандартной инфраструктуре тестирования Android. Robolectric по-прежнему полезен для некоторых случаев, но мне было проще управлять приложением, так что большинство моих чистых классов Java являются модулями java-библиотеки, которые тестируются на устройствах с помощью junit и Android-специфичных с платформой тестирования Android. –

Смежные вопросы