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

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

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

Попытка добавить мои тесты JUnit в instrumentTest не помогла мне. Я могу запустить его как тест Android (для чего это каталог), но это не то, что я ищу - я просто хочу запустить простой тест JUnit. Я попытался создать конфигурацию запуска JUnit для этого класса, но это также не сработало - я полагаю, потому что я использую каталог, помеченный как Android Test вместо Source.

Если я создаю новую исходную папку и помечаю ее как таковой в структуре проекта, это будет очищено в следующий раз IntelliJ обновляет конфигурацию проекта из файлов сборки gradle.

Каков наиболее подходящий способ настройки тестов JUnit в проекте Android на gradle на IntelliJ? Какую структуру каталогов использовать для этого?

Ответ 2

Обычно вы не можете. Добро пожаловать в мир Android, где все тесты должны выполняться на устройстве (кроме Robolectric).

Основная причина заключается в том, что на самом деле у вас нет источников фреймворка - даже если вы убедите среду IDE выполнить тест локально, вы сразу же получите исключение "Stub! Not Implement". "Зачем?" вы можете задаться вопросом? Поскольку android.jar, который дает вам SDK, на самом деле все вычеркнуто - все классы и методы есть, но все они просто бросают исключение. Это там, чтобы предоставить API, но не там, чтобы дать вам реальную реализацию.

Там замечательный проект под названием Robolectric, который реализует многие рамки только для того, чтобы вы могли запускать осмысленные тесты. В сочетании с хорошей макетной каркасной структурой (например, Mockito) она делает вашу работу управляемой.

Gradle плагин: https://github.com/robolectric/robolectric-gradle-plugin

Ответ 3

Введение

Обратите внимание, что на момент написания robolectric 2.4 является последней версией и не поддерживает библиотеку appcompat v7. Поддержка будет добавлена ​​в релиз robolectric 3.0 (пока еще нет ETA). Также ActionBar Sherlock может вызвать проблемы с robolectric.

Чтобы использовать 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.

(Вариант 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 плагин 0.13+ и robolectric 2.3

Buildscript (project/build.gradle)

Строка script - это файл build.gradle в корне вашего проекта. Там мне пришлось добавить robolectric gradle плагин в classpath

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)

В сборке script вашего модуля приложения используйте плагин 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 config)

app/src/androidTest/java

И назовите свои классы тестов, заканчивающиеся на Test (или снова обновляйте config), расширяя 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 где-то еще, вы можете перенести свои тестовые исходные файлы. Просто обновите конфигурацию gradle sourceSets.

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

        androidTest {
            setRoot('tests')
        }
    }

пакет org.junit не существует

Вы забыли добавить зависимость теста junit в приложении build script

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

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

java.lang.RuntimeException: Stub!

Вы используете этот тест с настройками запуска из 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 установлен в недопустимый каталог

См. этот вопрос SO для решения. Добавьте ниже представленный вам профиль 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, вам придется немного расширить файл build.gradle, чтобы студия Android могла находить ваши скомпилированные тестовые классы:

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

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

Еще несколько ресурсов

Лучшие статьи, которые я нашел по этому поводу:

Ответ 5

Для Android Studio 1.2 + настройка проекта для JUnit довольно проста. Попробуйте следовать этому руководству:

Это простейшая часть, создающая проект для JUnit:

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

Следуйте по предыдущей ссылке до тех пор, пока Запуск тестов

Теперь, если вы хотите интегрироваться с тестом интрументации, следуйте отсюда:

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

Ответ 6

Пожалуйста, ознакомьтесь с этим учебник на официальном сайте разработчиков Android. В этой статье также показано, как создавать макеты для вашего тестирования.

Кстати, вы должны заметить, что область зависимостей для простого теста JUnit должна быть "testCompile".