Настройка Robolectric в Android Studio не простоя задача, но решаемая!
Что мы имеем в начале:1 - Установленную Android SDK и последнюю версию Android Studio;
2 - Созданный по умолчанию проект и написано немного код, который нужно тестировать.
В коде приложения, есть функционал, который зависит от стандартных библиотек Java и может выполняться в JVM(Java Virtual Machine). Значит написанные для него Unit-тесты можно выполнить в самой JVM, без подключения Android устройства или эмулятора. Это ускоряет процесс разработки особенно, если вы используете методологию TDD(Test Driving Development). Для этого я выбрал фреймворк для Unit-тестирования - Robolectric, который используется многими Android разработчиками.
Robolectric, также позволяет тестировать классы зависящие от Android SDK, такие как: Activity, Fragments и т. д.. И все это без подключения устройства или эмулятора, в вашей JVM!
Это ускоряет процесс разработки, Unit-тесты запускаются без устройства, здорово, не правда ли!? Но есть одна проблемка, чтобы этого добиться, придется повозиться с настройками, да ладно поехали.
Как только вы создали проект, вы увидите подобную структуру и файл сборки build.gradle, что на рис. 1.
Рисунок 1. Структура приложения в Android Studio |
Перед тем как продолжить, нужно установить Android Studio Unit Test Plugin: https://github.com/evant/android-studio-unit-test-plugin
После долгих поисков в интернете и неудачных попыток настроить Robolectric для работы в Android Studio, я таки нашел способ все настроить так, чтобы работало.
Отправной точкой для меня послужил шаблон Android проекта для разработки через тестирование: https://github.com/robolectric/deckard-gradle
Общий файл сборки build.gradle стал выглядеть так:
// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.0.0'
classpath 'org.robolectric:robolectric-gradle-plugin:0.14.+'
}
}
allprojects {
repositories {
jcenter()
}
}
А файл сборки build.gradle самого Android приложения так:
apply plugin: 'com.android.application'apply plugin: 'android'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "ru.besttuts.stockwidget"
minSdkVersion 10
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
androidTest {
setRoot('src/test')
}
}
}
apply plugin: 'robolectric'
robolectric {
include '**/robolectric/**/*Test.class'
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.+'
androidTestCompile 'org.hamcrest:hamcrest-core:1.3'
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
androidTestCompile('junit:junit:4.12') {
exclude module: 'hamcrest-core'
}
androidTestCompile('org.robolectric:robolectric:2.4') {
exclude module: 'classworlds'
exclude module: 'commons-logging'
exclude module: 'httpclient'
exclude module: 'maven-artifact'
exclude module: 'maven-artifact-manager'
exclude module: 'maven-error-diagnostics'
exclude module: 'maven-model'
exclude module: 'maven-project'
exclude module: 'maven-settings'
exclude module: 'plexus-container-default'
exclude module: 'plexus-interpolation'
exclude module: 'plexus-utils'
exclude module: 'wagon-file'
exclude module: 'wagon-http-lightweight'
exclude module: 'wagon-provider-api'
}
}
apply plugin: 'idea'
idea {
module {
testOutputDir = file('build/test-classes/debug')
}
}
Обратите внимание на строки:
sourceSets {
androidTest {
setRoot('src/test')
}
}
По умолчанию Android Studio создает директорию для тестов под названием androidTest, которую понимает среда разработки и подсвечивает соответствующим образом. Чтобы придерживаться стандартов, я переименовал эту директорию в test и указал это среде разработки, как показано выше.
Обратите внимание на строки:
apply plugin: 'robolectric'robolectric {
include '**/robolectric/**/*Test.class'
}
Я создал директорию robolectric (D:\ideaWorkspace\StockWidget\android\src\test\java\ru\besttuts\stockwidget\robolectric\EconomicWidgetConfigureActivityTest.java), в которой будут находиться тесты созданные на базе Robolectric. При выполнении тестов Robolectic будет тестировать откомпилированные классы оканчивающиеся на *Test.class и находящиеся в директории/субдиректориях robolectric, как показано выше.
Не забываем нажать Sync Now для начала подгрузки зависимостей!
Далее напишем простенький тест (рис. 2), чтобы удостовериться в работоспособности нашей настройки.
Рисунок 2. Простенький Unit-тест для проверки |
gradlew clean test
Результат теста можно посмотреть по адресу: file:///D:/ideaWorkspace/StockWidget/android/build/test-report/debug/index.html, пример которого на рис. 3.
Рисунок 3. Пример результата теста |
Сейчас я опишу путь решения. Поехали.
Кликаете правой кнопкой по файлу теста -> в раскрывшемся контекстном меню кликаете по Run и выбираете обычный JUnit тест(не
С 99,99% вероятностью Вы получите ошибку:
!!! 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)
Копируем -classpath "...", рис. 4.Рисунок 4. Копируем -classpath "..." |
-classpath "C:\Program Files\Android\Android Studio\lib\idea_rt.jar;C:\Program Files\Android\Android Studio\plugins\junit\lib\junit-rt.jar;D:\ideaWorkspace\StockWidget\android\build\intermediates\classes\debug;C:\Android\android-sdk\platforms\android-21\android.jar;C:\Android\android-sdk\platforms\android-21\data\res;C:\Users\roman\.gradle\caches\modules-2\files-2.1\org.robolectric\robolectric-annotations\2.4\936c649cb0958d7fb5d3c09b31c56b3997f80650\robolectric-annotations-2.4.jar;...;C:\Users\roman\.gradle\caches\modules-2\files-2.1\com.almworks.sqlite4java\sqlite4java\0.282\745a7e2f35fdbe6336922e0d492c979dbbfa74fb\sqlite4java-0.282.jar"
Строчку выделенную жирным шрифтом: C:\Android\android-sdk\platforms\android-<21>\android.jar;C:\Android\android-sdk\platforms\android-<21>\data\res; необходимо вырезать и вставить в конец нашего -classpath, и не забывайте ставить разделители ';'.
Вместо <21> может быть другая версия Android SDK, которую вы используете!
После этого, также в конец нужно вставить: ;<D:\ideaWorkspace\StockWidget\>android\build\test-classes; - это путь до ваших откомпилированных тестовых классов вида *Test.class.
<D:\ideaWorkspace\StockWidget\> - вместо этого, вы должны вставить корневой путь до вашего проекта!
В конце мы получаем наш отредактированный -classpath:
-classpath "C:\Program Files\Android\Android Studio\lib\idea_rt.jar;C:\Program Files\Android\Android Studio\plugins\junit\lib\junit-rt.jar;D:\ideaWorkspace\StockWidget\android\build\intermediates\classes\debug;C:\Users\roman\.gradle\caches\modules-2\files-2.1\org.robolectric\robolectric-annotations\2.4\936c649cb0958d7fb5d3c09b31c56b3997f80650\robolectric-annotations-2.4.jar;...;C:\Users\roman\.gradle\caches\modules-2\files-2.1\com.almworks.sqlite4java\sqlite4java\0.282\745a7e2f35fdbe6336922e0d492c979dbbfa74fb\sqlite4java-0.282.jar;C:\Android\android-sdk\platforms\android-21\android.jar;C:\Android\android-sdk\platforms\android-21\data\res;D:\ideaWorkspace\StockWidget\android\build\test-classes"
Открываем Edit Configurations... -> находим Run/Debug Configurations настройки для запуска нашего Unit-теста и в VM options копируем наш измененный -classpath, рис. 5.
Рисунок 5. Вставка -classpath в VM options |
Рисунок 6. Gradle конфигурация для запуска команды тест |
Рисунок 7. Добавления Gradle конфигурации в Before Launch наше Unit-теста |
Нажимаем Apply -> Ok, сохраняем настройки запуска теста.
Далее запускаем наш тест, и все должно заработать, рис. 8!
Рисунок 8. Наш тест прошел без ошибок |
Все описал как сам настроил, ничего не забыл надеюсь. Если возникли вопросы пишите, постараюсь ответить. Лучше бы это все в видео формате выложить, чтобы было более понятно, как считаете?
Спасибо за внимание!