Как переключить / изменить testInstrumentationRunner динамически с помощью gradle

Мой проект состоит из двух разных групп тестов. Одна группа работает только с AndroidJUnitRunner по умолчанию, другой должен быть запущен с помощью специальной реализации. TestRunner extends MonitoringInstrumentation .

В настоящее время я переключаю testInstrumentationRunner , редактируя build.gradle каждый раз, когда мне нужно запустить другую группу тестов:

 android{ defaultConfig { //testInstrumentationRunner "my.custom.TestRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } } 

Я знаю, что у флейворов может быть свой собственный testInstrumentationRunner но у моего текущего приложения уже есть 2 flavourDimensions . Использование ароматов на самом деле предназначено для разных версий приложения. Мне нужны 2 версии тестового приложения, оба тестируют одно и то же приложение с различными testInstrumentationRunner s.

Я попытался изменить testInstrumentationRunner , итерации по всем тестовым вариантам. На самом деле существует несколько свойств testInstrumentationRunner :

 android.testVariants.all { TestVariant variant -> //readonly variant.variantData.variantConfiguration.instrumentationRunner variant.variantData.variantConfiguration.defaultConfig.testInstrumentationRunner } для android.testVariants.all { TestVariant variant -> //readonly variant.variantData.variantConfiguration.instrumentationRunner variant.variantData.variantConfiguration.defaultConfig.testInstrumentationRunner } 

Но как только android.testVariants называется, сборка настроена, и все изменения не отражаются в сборке.

Как я могу изменить testInstrumentationRunner (из плагина градиента) динамически?

Я бы предпочел иметь две разные задачи градации, каждый из которых использует другой testInstrumentationRunner но тестируя тот же вариант. Поскольку я намерен создать плагин gradle, решение должно работать как плагин.

Начиная с плагина 1.3 для Android, вы можете создавать отдельные тестовые модули. Каждый из этих тестовых модулей может иметь свой собственный testInstrumentationRunner.

Подробный пример приведен в примере проекта AndroidTestingBlueprint на github.

Решение от @ johan-stuyts, получившего награду, отлично работает (или, по крайней мере, с плагином android gradle 1.2). Но он использует частные API, и создание отдельного модуля проще и надежнее.

У меня была аналогичная проблема, я использовал задачу графа Graph. Основываясь на вашем заявлении «Мой проект имеет две разные группы тестов». Я предполагаю, что у вас разные задачи определены, я назову их testGroupOne и testGroupTwo:

 task testGroupOne{ } task testGroupTwo{ } gradle.taskGraph.whenReady {taskGraph -> if(taskGraph.hasTask(testGroupOne)){ testInstrumentationRunner "my.custom.TestRunner" } else if (taskGraph.hasTask(testGroupTwo)){ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } } 

Это позволяет вам установить значение testInstrumentationRunner после настройки, но до его выполнения.

Считаете ли вы использование параметра console в качестве переключателя между двумя конфигурациями? Так просто:

 android { defaultConfig { if (project.ext.has("customRunner")) { testInstrumentationRunner "my.custom.TestRunner" } else { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } } } 

А затем, например, запустите gradlew aDeb -PcustomRunner если вы хотите протестировать с помощью пользовательского runner или gradlew aDeb для использования по умолчанию.

Я знаю, что это не ракетная наука, а проще, да? Вы также можете использовать его в своем плагине, просто получите объект Project и выполните аналогичную работу.

Это частичное решение, но, возможно, это сделает вещи немного менее громоздкими для вас: это не позволяет вам запускать тесты с обоими тестовыми бегунами в одной и той же сборке. Если вы хотите, чтобы вам пришлось клонировать все экземпляры задач DeviceProviderInstrumentTestTask , которые, на мой взгляд, слишком сложны и хрупки.

Это работает для меня (Gradle 2.4 и Android build tools 1.2.3). Он использует внутренние API-интерфейсы, поэтому возможно, что это больше не работает со следующей версией инструментов сборки Android.

Вы должны изменить задачи, сгенерированные подключаемым модулем Android после оценки проекта. Эти изменения затем будут использоваться тестовыми задачами. Свойством, которое фактически изменяет используемый тестовый бегун, является task.testVariantData.variantConfiguration.testedConfig.mergedFlavor.testInstrumentationRunner . Вместо внесения этих изменений во время фазы конфигурации (т. Е. Вне задачи) изменения применяются с использованием задачи, поэтому ваш тестовый бегун используется только по запросу. useMyTestRunner тестовые задачи запускаться после useMyTestRunner (если последний является частью сборки), имя класса тестового бегуна будет изменено при запуске тестовой задачи:

 project.afterEvaluate { task useMyTestRunner << { tasks.withType(com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.class) { task -> task.testVariantData.variantConfiguration.testedConfig.mergedFlavor.testInstrumentationRunner = 'com.mycompany.MyTestRunner' } } tasks.withType(com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.class) { task -> task.mustRunAfter useMyTestRunner } } 

Теперь вы можете запускать тесты, используя тестовый бегун по умолчанию, настроенный для вкуса (-ов):

 gradle :myApp:connectedAndroidTest 

Если вы хотите запустить тесты с помощью своего тестового бегуна, используйте:

 gradle :myApp:connectedAndroidTest :myApp:useMyTestRunner 

Я не добавлял проверки для null для любого из свойств, полученных с помощью task.testVariantData.variantConfiguration.testedConfig.mergedFlavor.testInstrumentationRunner . Вы должны добавить их для надежности. Я думаю, что, по крайней мере, testedConfig нуждается в внимании. См. getInstrumentationRunner() на странице https://android.googlesource.com/platform/tools/build/+/master/builder/src/main/java/com/android/builder/VariantConfiguration.java

Вы можете использовать импорт для com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask в верхней части вашего файла сборки, поэтому вам нужно использовать простое имя класса.