Why can't I use gradle task connectedDebugAndroidTest in my build script? - android

I can refer to connectedCheck task (which came from android plugin) from my build script:
connectedCheck.finalizedBy AndroidShowTestResults
But trying to use connectedDebugAndroidTest (which came from android plugin too)
connectedDebugAndroidTest.finalizedBy AndroidShowTestResults
gives me
Error:(48, 0) Could not find property 'connectedDebugAndroidTest' on project ':app'.
And if I try
task connectedDebugAndroidTest << {print '123'}
it curses me with
Error:Cannot add task ':app:connectedDebugAndroidTest' as a task with that name already exists.
I don't undestand why I cannot refer to connectedDebugAndroidTest?
Available gradle tasks are shown below:

The android plugin defers the addition of several tasks especially those that have buildType or flavor names in them till a very late stage of the configuration phase. Which in turn means if you try to refer to these yet-to-be-added-tasks by name, you're likely to see a "does not exist" type error messages. If you want to add dependencies around deferred-created tasks, you should wait until configuration is complete:
gradle.projectsEvaluated {
connectedDebugAndroidTest.finalizedBy AndroidShowTestResults
}
Alternatively, you can add a listener to task-graph events, so you can do stuff as soon as a certain task is added to task-graph:
tasks.whenTaskAdded { task ->
if (task.name == 'connectedDebugAndroidTest') {
task.finalizedBy AndroidShowTestResults
}
}

Try
task connectedTest(dependsOn: ["connectedDebugAndroidTest"]){
}
connectedTest.finalizedBy "AndroidShowTestResults"

I think you should try to open test and rebuild.

Related

Generated code stays in build folder after Android Studio Build

I am using a gradle task to generate some code for my API and store this code into the build folder. When I am building my application the process deletes the build folder.
Is there a way to call my code generation task between the folder deletion and the start of the compilation?
I am not a Gradle expert, so their might be better answers!
In your build.gradle you can create custom tasks and make them depend on other tasks:
// this is your new task
task generateCode() {
description 'Generates some code...'
doLast {
println("generateCode")
// do your code generation here
}
}
// put the name of the task you wanna depend on, like: compileSources
project.task("compileSources").dependsOn generateCode
When you call this task ./gradlew compileSources you should see that the custom task generateCode gets executed first.
After allot of trying , i found the solution .
In the build.gradle i had to add the preBuild.finalizedBy(generateCode)

Is there a way to make gradle task lintRelease do nothing when executed for a particular module?

Currently lintRelease, task depends on the compilation task, and for some modules (which I dont care about since its only used for testing purposes), I want lintRelease to do nothing, just print Not supported is that possible with gradle KTS?
Basically this question is about gradle task replacement, I want to replace the lintRelease gradle task with a task that does nothing.
If you are thinking
You can skip lint checking for debug/release builds
The lintRelease task is manually triggered at the moment by a shell script, so thats not an option, I need this task to not do anything for this particular module lets call it module X
Try this at the top of the Gradle file
tasks.whenTaskAdded { task ->
if (task.name.equals("lint")) {
task.enabled = false
}
}
Even this can also help
android {
lintOptions {
tasks.lint.enabled = false
}
}

How to copy debug assets for unit tests

I have an android library gradle project. And I need to copy some files to assets folder for robolectric unit tests.
To do it I've defined a copy task:
task copyDebugAssets(type: Copy) {
from "${projectDir}/somewhere"
into "${buildDir}/intermediates/bundles/debug/assets"
}
but I can't add this task as a dependency for processDebugResources task:
processDebugResources.dependsOn copyDebugAssets
because of this error:
Could not get unknown property 'processDebugResources' for object of type com.android.build.gradle.LibraryExtension.
Now I have to manually execute this task before unit test:
./gradlew clean copyDebugAssets test
How can I solve it?
The android plugin adds several tasks dynamically. Your .dependsOn line doesn't work because at the time gradle is trying to process this line, processDebugResources task yet available. You should tell gradle to add the dependency as soon as the upstream task is available:
tasks.whenTaskAdded { task ->
if (task.name == 'processDebugResources') {
task.dependsOn copyDebugAssets
}
}
Why copy? Configure where the assets should be pulled from:
android {
// other cool stuff here
sourceSets {
androidTest {
assets.srcDirs = ['../testAssets']
}
}
}
(replacing ../testAssets with a path to where the assets should come from)
I have used this successfully with androidTest for instrumentation testing. AFAIK, it should work for test or any other source set.

Could not find property 'uninstallDebug' on project

In my project I want to run my custom task "MyTask" to run before uninstall happens. Code for the same is
uninstallDebug.dependsOn "MyTask"
When I run this, it fails with an error
Could not find property 'uninstallDebug' on project
whereas, I see a gradle task listed in the Gradle window with that name.
What may be going wrong?
project.afterEvaluate { p ->
p.tasks.uninstallDebug.doFirst {
println 'before uninstall'
}
}
gradle.taskGraph.whenReady {
// if your MyTask is in the same project
uninstallDebug.dependsOn "MyTask"
// if it is else where
uninstallDebug.dependsOn project("someProject").project("subProject).tasks["MyTask"]
}
uninstallDebug along with several other tasks, especially those that have flavor or buildType name in their name are created and added to the gradle taskGraph quite late in the configuration step by the android plugin. What that means, as you have discovered is that you may not be able to refer to them by name early in the config step since they do not exist yet.
The way around this as the other answers point out is to wait until the tasks in question are added to the taskgraph. You can use your line uninstallDebug.dependsOn "MyTask" in either gradle.taskgraph.whenRead{} or project.afterEvaluate {}

Want to run a custom gradle task only when running Unit test

How to set up gradle to run a particular custom copy task, only when running unit tests?
EDIT
I want to run these tasks when i press build, i. e only in the flavor of the build with unit test execution included.
I've finally found the solution, with the help of this documentation which presents all the tasks that run during build, test, release etc. in a very concise manner. So by making tasks clean, preBuild depend on my copyTask I can ensure that the copy task is run every time the project is cleaned or built.
But since I don't want to run this during building or cleaning process but want to run it when I only run tests, I identified a task that compiles release unit test sources called the compileReleaseUnitTestSources but just mentioning it in build.gradle as
compileReleaseUnitTestSources.dependsOn(myCopyTask)
doesn't actually work, because gradle will give an error saying it cannot find the task compileReleaseUnitTestSources as for some reason that task is not available yet. Instead by enclosing it in a afterEvaluate block we can ensure that this block is executed after all tasks are evaluated, that way we have access to that task now, So finally I added this to my build.gradle
afterEvaluate {
compileReleaseUnitTestSources.dependsOn(copyResDirectoryToClasses)
}
All the answers here mention to use the dependsOn keyword to attach my task to another task that is run during general build/test execution, but none of them mentioned how to go around the problem where gradle is not able to find the tasks even though you know for sure that these tasks were available and run during build/test execution.
you have to set up a "customCopyTask" and make the "test-task" which does the unittests depend on the "customCopyTask" like this
task customCopyTask(type: Copy) {
from sourceSets.test.resources
into sourceSets.test.output.classesDir
}
test.dependsOn customCopyTask
You can make some task finalizing another, in that case this task will run only if another one was called, right after it. This could be done as:
task runUnitTest << {
println 'running tests'
}
task copyTestResults << {
println 'copying results'
}
//make copyTestResults finalize runUnitTest
runUnitTest.finalizedBy copyTestResults
You can read about it in the official user guide.
Additionally, if your unit test could be up-to-date and you don't want to run you copy task in that case, you can check the test task status and skip copy-task, as:
task copyTestResults {
doFirst {
//chtck anothe task status and skip this one if it didn't actually work
if (!tasks.getByName("runUnitTest").getState().didWork) {
throw new StopExecutionException();
}
}
doLast{
println 'copying results'
}
}
Or, if you just need to run copy-task before unit tests, make the test task depending on copy-task by setting it's dependsOn property, read about it with a number og examples here

Categories

Resources