Add New Dependency Configuration That is Used For a Specific Task - android

I'm trying to setup an Android project, we have certain kind of tests (Tests A) that run differently from other tests (Tests B) that require their own dependencies that can't be included when Tests B run.
I'm trying to add a new configuration that extends androidTestCompile with this code in my build.gradle file:
configurations {
myTestCompile.extendsFrom('androidTestCompile');
}
As per http://chimera.labs.oreilly.com/books/1234000001741/ch04.html#DEPENDENCY-CONFIGURATIONS This doesn't work, it gives me an error 'method not found extendsFrom()'.
I then also don't know how to use certain configurations for a task.
Any help would be appreciated, cheers.

You have to declare the configuration first.
configurations {
myTestCompile
myTestCompile.extendsFrom androidTestCompile
}
Edit
You can then declare a test task that used that configuration.
task testB(type: Test) {
classpath = configurations.myTestCompile
}

Related

How to add gradle's task parameter in Android Studio?

We are going to debug our Android app by adding some properties in app.properties and pre-process it in the Kotlin codes.
We wrote build.gradle like:
task dailytest {
doLast {
File testProperty = new File('assets/app.properties')
testProperty.append("\ndaily_test=true")
testProperty.append("\nfps_sample_interval_ms=")
testProperty.append(fps_sample_interval_ms)
testProperty.append("\ndrop_stack_sample_interval_ms=")
testProperty.append(drop_stack_sample_interval_ms)
testProperty.append("\nmin_drop_count_to_log=")
testProperty.append(min_drop_count_to_log)
}
}
And we compile it in command line using:
./gradlew dailytest -Pfps_sample_interval_ms="100" -Pdrop_stack_sample_interval_ms="100" -Pmin_drop_count_to_log="1" :connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.myapp.sub.MainActivityTest#test_click_shelf
I was wondering if maybe we could run this test case in Android Studio by adding some confirmations?
We did try to add ::dailytest in the Before launch part, but we couldn't manage to find a way to add the custom parameters.
You can have an afterEvaluate block in your build.gradle to run your task when you build your app, something like this:
afterEvaluate {
lint.dependsOn dailytest
}

Isolating test APK build

I have a situation where in an Android project with instrumentation tests I have all of the production code precompiled and ready to be installed as an .apk (a React Native environment).
Whenever I run instrumentation tests, I initially build the AndroidTest .apk using Gradle by running:
./gradlew assembleDebugAndroidTest -DtestBuildType=debug
(i.e. in a pretty standard way).
Trouble is that despite explicitly specifying only the xxxAndroidTest task, all of the production code assembly Gradle tasks are run as well. This is an extreme time waster to me since - as I explained, the production apk is already there, and thus code compilation (and packaging, signing, etc.) is scarce.
In essence, I have no dependency in production code from the instrumentation code -- even the ActivityTestRule I use is created dynamically and isn't directly bound to my main activity:
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(launchIntent, 0);
Class<?> activityClass = Class.forName(resolveInfo.activityInfo.name);
ActivityTestRule<?> activityTestRule = new ActivityTestRule(activityClass, false, false);
Question is: How can I isolate / restrict Gradle's work so it would only include test-related tasks? I even tried inspecting the tasks tree using this Gradle plugin, but couldn't find a clear place to "cut the tree" down.
Well so far I've come up with this (heuristic) solution, that does 2 things:
I noticed that most of the time that goes to waste is due to sub-projects that are not needed for the job. Therefore, the solution provides an easy way to exclude implementations from test building.
Out of the tasks remaining in the list, still - the plugin iteratively force-disables tasks that are not related but run nonetheless.
It boils down to this helper Gradle script:
// turbo-test-apk.gradle
def isEnabled = System.getProperty('TURBO_TEST_APK') != null
project.ext.dependenciesExcludeTest = { depsClosure ->
if (!isEnabled) {
dependencies(depsClosure)
}
}
gradle.taskGraph.whenReady { graph ->
if (isEnabled) {
def disabledTasks = new ArrayList<Task>(graph.allTasks.size())
[/.*JsAndAssets.*/, /package.*Release/, /package.*Debug/, /compile.*/, /.*[Pp]roguard.*/, /.*[Nn]ew[Rr]elic.*/, /.*AndroidTest.*/].forEach { regex ->
graph.allTasks.findAll { it.name ==~ regex }.forEach({ task ->
disabledTasks.add(task)
task.enabled = false
})
}
graph.allTasks.findAll { it.name ==~ /.*AndroidTest.*/ }.forEach({ task ->
task.enabled = true
})
println '--- Turbo test build: task scanning ---'
disabledTasks.forEach { task ->
if (!task.enabled) {
println 'Force-skipping ' + task
}
}
println '---------------------------------------'
}
}
Namely, the dependenciesExcludeTest enabled the exclusion of unwanted subprojects, and the task-graph-ready callback does the disabling. NOTE that the regex list is custom made, and is not generic. It makes sense for my project as react native projects have a heavy-weight JS-bundling tasks called bundleJsAndAssets, and I also have new relic installed. Nevertheless, this can be easily tailored to any project.
Also, the app.gradle looks something like this:
apply plugin: 'com.android.application'
apply from: './turbo-test-apk.gradle'
dependencies {
implementation "org.jetbrains.kotlin:$kotlin_stdlib:$kotlinVersion"
implementation "com.android.support:support-v4:$supportLibraryVersion"
implementation "com.android.support:appcompat-v7:$supportLibraryVersion"
// etc.
}
// These will be excluded when executing test-only mode
dependenciesExcludeTest {
implementation project(':#react-native-community_async-storage')
implementation project(':any-unneeded-sub-project')
}
So when gradle is run like this (i.e. with a custom TURBO_TEST_APK property):
./gradlew assembleDebugAndroidTest -DtestBuildType=debug -DTURBO_TEST_APK
the script will apply its work and reduce the overall build time.
This solution isn't optimal: tricky to maintain, doesn't omit all of the unnecessary work. I'd be very happy to see more effective solutions.

Gradle Espresso - Task connectedProductFlavorBuildTypeAndroidTest not found in root project

My build.gradle is like this:
productFlavors {
mainFlavor {
// ...
}
}
buildTypes {
debug {
// ...
}
buildType1 {// I write mock data classes for Espresso tests here
// ...
}
}
./gradlew tasks includes connectedMainFlavorDebugAndroidTest but not connectedMainFlavorBuildType1AndroidTest.
Why?
I want to specifically run Espresso tests for buildType1 only.
I'm not the owner of the project, I'm not allowed to use either mainFlavorDebug or someNewFlavorDebug to write Espresso tests
The answer from official documentation:
By default, all tests run against the debug build type. You can change
this to another build type by using the testBuildType property in your
module-level build.gradle file. For example, if you want to run your
tests against your "staging" build type, edit the file as shown in the
following snippet.
android {
...
testBuildType "staging" }

Gradle android, how to exclude a single unit test

I have an android project with unit and integration tests in the same folder. If I run ./gradlew test all of them are run, but I just need to exclude the cucumber tests from running, at the moment I just need to actually exclude to run the class with the annotation #RunWith(Cucumber.class).
Any suggestions?
The usual way of adding a test closure like below does not work for some reason with gradle android plugin:
test {
exclude 'com/example/MyTest.*'
}
Instead I have found the following option. Use the #Ignore annotation on your test(s). You can also conditionally ignore the test (e.g. based on a system property like RUN_AUTOMATION_TEST=false) using this answer
If you are using spock rather than junit then use something like this:
#IgnoreIf( {System.getProperty('RUN_AUTOMATION_TESTS') == null} )
public class MainScreenSpec extends BaseUiAutomationSpec {
}

Intellij not recognizing directory as tests

I added another source set, and a task of type test that uses that source set. I can execute the task and run the tests fine.
However, Intellij doesn't consider this src/newTests/java as tests. If I 'Mark directory as test sources' in the UI, it will forget it he next time build.gradle is synced. How do I make it remember this?
Try this:
android {
sourceSets {
test {
java.srcDir file('src/newTest/java')
}
}
}
Result:

Categories

Resources