Запуск простих тестів JUnit на Android Studio (IntelliJ) при використанні конфігурації на основі Gradle


78

Я використовую Android Studio/IntelliJдля побудови існуючого Androidпроекту і хотів би додати кілька простих JUnitмодульних тестів. Яка правильна папка для додавання таких тестів?

GradleПлагін android визначає структуру каталогів src/main/javaдля основного вихідного коду та src/instrumentTest/javaдля Androidтестів.

Спроба додати свої тести JUnit в instrumentTest мені не спрацювала. Я можу запустити його як Androidтест (саме для цього здається цей каталог), але це не те, що я шукаю - я просто хочу виконати простий JUnitтест. Я спробував створити конфігурацію запуску JUnit для цього класу, але це також не спрацювало - я припускаю, тому що я використовую каталог, який позначений як AndroidTest замість Source.

Якщо я створив нову вихідну папку та позначив її як таку в Структурі проекту, це буде IntelliJвидалено наступного разу, коли оновить конфігурацію проекту з файлів збірки gradle.

Який найбільш доцільний спосіб налаштування тестів JUnit у проекті Android на основі gradle IntelliJ? Яку структуру каталогів використовувати для цього?


На жаль, я не можу вам допомогти з тестами, оскільки я все ще борюся з цим, але ви можете використовувати це, щоб зупинити IntelliJ витираючи вихідні папки: java.srcDirs = ['src/main/java','src/instrumentTest/java']у sourceSetsрозділіbuild.gradle
Роб Холмс

Його не цікаво налаштовувати, ані просто підтримувати, але я якось запустив його, використовуючи /src/androidTest/javaпапку за замовчуванням з роболектричними тестами JUnit, див .: stackoverflow.com/a/25473702/1406325
Фло

Android Studio тепер підтримує тестування локальних блоків за допомогою JUnit 4: stackoverflow.com/a/30273301/885464
Лоренцо Полідорі,

Оновлення @Julian Cerruti: Демонстрація Android Studio про те, як запустити testcase goo.gl/ac06C0 та приклад запуску тесту мережевих дзвінків goo.gl/bQFlmU
nitesh

Структури каталогів для тестів та тестових класів повинні відповідати. Ось як це легко зробити:
stackoverflow.com/a/36057080/715269

Відповіді:


23

Що стосується Android Studio 1.1, відповідь тепер проста: http://tools.android.com/tech-docs/unit-testing-support


4
Чи означає це, що Robolectric більше не корисний? Чи буде це по суті робити те саме?
Девід Аргайл Такер

1
Примітка: Починаючи з Android Studio 2.0 Beta5, у посиланні, що описує селектор "Перевірити артефакт", бракує, і обидва режими (junit та insttrumentation) увімкнено одночасно за замовчуванням. Дивіться тут для отримання додаткової інформації stackoverflow.com/questions/35708263/…
Патрік Фавр

36

Як правило, ви не можете. Ласкаво просимо у світ Android, де всі тести повинні виконуватися на пристрої (крім Robolectric).

Основна причина полягає в тому, що у вас насправді немає джерел фреймворку - навіть якщо ви переконаєте IDE запустити тест локально, ви одразу отримаєте виняток "Stub! Не реалізовано". - Чому? Ви можете здивуватися? Оскільки те, android.jarщо надає вам SDK, насправді все заглушено - всі класи та методи є, але всі вони просто створюють виняток. Він існує, щоб надати API, але не там, щоб дати вам реальну реалізацію.

Існує чудовий проект під назвою Robolectric, який реалізує велику кількість фреймворків лише для того, щоб ви могли проводити змістовні тести. У поєднанні з хорошим макетним фреймворком (наприклад, Mockito) це робить вашу роботу керованою.

Плагін Gradle: https://github.com/robolectric/robolectric-gradle-plugin


1
Дякую, Дейлан. Я переслідую прості тести, які не використовують жодну інфраструктуру Android, тому будь-яким шляхом слід створити новий проект, як ви пропонуєте, або налаштувати конфігурацію Gradle Android для проведення регулярних тестів. На жаль, я все ще не зміг змусити його запрацювати - він продовжує зазнавати збіїв з тієї чи іншої причини - але опублікую результат, якщо я коли-небудь змушу його запрацювати
Джуліан Черруті

1
У цьому випадку ви хочете створити новий звичайний проект Java Gradle (тобто apply plugin: 'java'), додати його до 'settings.gradle', встановити як залежність від вашого проекту Android ( compile project(':plainJavaProjectName')) і просто запустити testзавдання. (Не перевірено, але неодмінно повинно працювати!)
Делян

3
Тести в простому проекті Java gradle чудово працюють із командним рядком, але не всередині Android Studio, де я отримую помилку "клас не знайдений MyTestClass". Це дивно, оскільки AS і командний рядок повинні використовувати gradle однаково.
lukas

1
Уникайте gradle, якщо ви хочете скористатися тестуванням JUnit, кращим варіантом є maven.
Jeroen

3
Чи можете ви обґрунтувати це твердження? Чому Maven краще?
RichieHH

32

Вступ

Зауважте, що на момент написання роботи robolectric 2.4 є останньою версією і не підтримує appcompat v7бібліотеку. Підтримка буде додана у версії robolectric 3.0 (ще немає часу прибуття ). Також ActionBar Sherlockможе спричинити проблеми з роболектриком.

Щоб використовувати Robolectric в Android Studio, у вас є 2 варіанти:

(Варіант 1) - Запуск тестів JUnit з Android Studio за допомогою модуля Java

Ця техніка використовує модуль java для всіх ваших тестів із залежністю від вашого модуля android та спеціальний тест-драйвер з деякою магією:

Інструкції можна знайти тут: http://blog.blundellapps.com/how-to-run-robolectric-junit-tests-in-android-studio/

Також перевірте посилання в кінці цього допису для запуску тестів від android studio.

(Варіант 2) - Запуск тестів JUnit з Android Studio за допомогою плагіна robolectric-gradle-plugin

Я зіткнувся з кількома проблемами під час налаштування тестів junit для запуску з gradle в Android Studio.

Це дуже базовий зразок проекту для запуску тестів junit із проекту на основі gradle в Android Studio: https://github.com/hanscappelle/android-studio-junit-robolectric Це було протестовано з Android Studio 0.8.14, JUnit 4.10, robolectric gradle plugin 0.13+ та robolectric 2.3

Buildscript (project / build.gradle)

Сценарій збірки - це файл build.gradle у кореневій частині проекту. Там мені довелося додати плагін robolectric gradle до шляху до класу

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.robolectric:robolectric-gradle-plugin:0.13.+'

    }
}

allprojects {
    repositories {
        jcenter()
    }
}

Проект buildscript (App / build.gradle)

У сценарії збірки вашого модуля програми використовуйте robolectricплагін, додайте robolectricконфігурацію та додайте androidTestCompileзалежності.

apply plugin: 'com.android.application'
apply plugin: 'robolectric'

android {
    // like any other project
}

robolectric {
    // 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 {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    androidTestCompile 'org.robolectric:robolectric:2.3'
    androidTestCompile 'junit:junit:4.10'
}

Створіть тестові класи JUnit

Тепер поставте тестові класи в місце за замовчуванням (або оновіть конфігурацію gradle)

app/src/androidTest/java

І назвіть свої класи тестування, що закінчуються тестом (або знову оновити конфігурацію), розширюючи junit.framework.TestCaseта анотуючи методи тестування за допомогою @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;
    }
}

Виконайте тести

Далі виконайте тести, використовуючи gradlew з командного рядка (зробіть його виконуваним, використовуючи, chmod +xякщо потрібно)

./gradlew clean test

Вихідні дані:

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

Вирішення проблем

каталоги альтернативних джерел

Так само, як ви можете мати свої вихідні файли Java кудись ще, ви можете перемістити свої тестові вихідні файли. Просто оновіть sourceSetsконфігурацію gradle .

    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }

        androidTest {
            setRoot('tests')
        }
    }

пакет org.junit не існує

Ви забули додати залежність тесту junit у сценарій збірки додатків

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])

    androidTestCompile 'org.robolectric:robolectric:2.3'
    androidTestCompile 'junit:junit:4.10'
}

java.lang.RuntimeException: Стуб!

Ви запускаєте цей тест із конфігураціями запуску з Android Studio замість командного рядка (вкладка Термінал в Android Studio). Щоб запустити його з Android Studio, вам доведеться оновити app.imlфайл, щоб внизу був вказаний запис jdk. Дивіться приклад deckard-gradle для деталей.

Повний приклад помилки:

!!! 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)
    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)

ПОМИЛКА: для JAVA_HOME встановлено недійсний каталог

Див. Це запитання щодо вирішення проблеми. Додайте наведений нижче експорт до свого профілю bash:

export JAVA_HOME=`/usr/libexec/java_home -v 1.7`  

Повний журнал помилок:

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.

Тестовий клас не знайдено

Якщо ви хочете запустити свої тести з Android Studio Junit Test runner, вам доведеться трохи більше розгорнути файл build.gradle, щоб андроїд-студія могла знайти ваші складені тестові класи:

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
    testLocalCompile 'junit:junit:4.11'
    testLocalCompile 'com.google.android:android:4.1.1.4'
    testLocalCompile 'org.robolectric:robolectric: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
    androidTestCompile 'junit:junit:4.11'
    androidTestCompile 'com.google.android:android:4.1.1.4'
    androidTestCompile 'org.robolectric:robolectric: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.compileClasspath += files(buildDir)
        sourceSets.testLocal.runtimeClasspath += files(buildDir)
    }

    classpath = sourceSets.testLocal.runtimeClasspath
}

check.dependsOn localTest

з: http://kostyay.name/android-studio-robolectric-gradle-getting-work/

Ще трохи ресурсів

Найкращі статті, які я знайшов навколо цього:


4

Тепер це підтримується в Android Studio, починаючи з плагіна Android Gradle 1.1.0, перевірте це:

https://developer.android.com/training/testing/unit-testing/local-unit-tests.html

Зразок програми з локальними модульними тестами на GitHub:

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


Посилання на github недоступне
Rahul Hawge

1

Для Android Studio 1.2+ налаштування проекту для JUnit досить просте, спробуйте дотримуватися цього підручника:

Це найпростіша частина налаштування проекту для JUnit:

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

Переходьте за попереднім посиланням до " Запуск тестів "

Тепер, якщо ви хочете інтегруватися з тестом інтрументації, дотримуйтесь тут:

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


0

Перегляньте цей посібник на офіційному веб-сайті розробників Android. У цій статті також показано, як створити макети для тестування.

До речі, слід зазначити, що область залежностей для простого тесту JUnit має бути "testCompile".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.