Unable to run Robolectric unit test with debugger in Android Studio - android

I've been successfully running Robolectric unit tests under the debugger in Android Studio since version 0.6.1
Now I am unable to and get the following error
ERROR: transport error 202: connect failed: Connection refused
ERROR: JDWP Transport dt_socket failed to initialize, TRANSPORT_INIT(510)
JDWP exit error AGENT_ERROR_TRANSPORT_INIT(197): No transports initialized [../../../src/share/back/debugInit.c:750]
Could not write standard input into: Gradle Test Executor 1.
java.io.IOException: Broken pipe
I have always set the use in-process build flag unchecked in the compile settings and although I am currently using AS 0.8-14, I have gone back and tried 0.8-11, 0.8-9 and 0.6-1 and none of them work now. I'm using android build tools version 19.1.0 (and have been for some time and it does work with them).
Could it be some local security setting under Mac OS X? Any assistance would be gratefully received.
** Update **
I have discovered that the issue is caused by running an additional JavaExec task before running the unit test tasks. It seems that gradle is running the JVM for the first task and passing debug arguments to it e.g. -agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=49807 The task completes and the JVM exits. Gradle then runs the actual unit test and expects the new JVM to listen on the same port for the debugger to connect - which it doesn't and so the connection failure arises.
How can I either prevent the prior task (an ormlite database compile task) from running under the debugger or force gradle to recognise that the unit test task will run using a new JVM and so change the jvmArgs for the unit test to reflect the new debug port?

I fixed this by changing the database compilation task to be an Exec task rather than a JavaExec task. The exec task was defined as follows and so executed the database compilation as an external java process, not a gradle invoked one. This prevented the debug JVM being 'consumed' by the database compilation task.
task (taskName type: Exec) {
def mainClass = "com.some.class"
def classPath = "${buildDir}/intermediates/classes/${flavorName}/${buildType.name}" + ":" + configurations.databaseCompile.asPath
commandLine "java", "-cp", classPath, mainClass, configDirName
}

Related

"Unknown block type" reading JaCoCo execution data files from Android

I wanted:
Code coverage to run reliably against the instrumented tests
Tests to be isolated from each other
I'm new to Android development, but experienced with other development and tooling.
So I looked for the documented options and added the following to my build.gradle:
android {
defaultConfig {testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
testInstrumentationRunnerArguments useTestStorageService: 'true'
}
buildTypes {
debug {
testCoverageEnabled true
}
}
I also have a custom task to generate the report:
task coverageReport(type: JacocoReport) {
sourceDirectories.setFrom(fileTree(
dir: "$project.buildDir/src/main/java"
))
classDirectories.setFrom(fileTree(
dir: "$project.buildDir/build/intermediates/javac/debug",
))
executionData fileTree(dir: project.buildDir, includes: [
"outputs/code_coverage/debugAndroidTest/connected/*/*.ec"
])
}
Now what I see when running the tests and generating the report, is that about 10% of the time it hits what looks like a corrupted .ec file. (the rest of the time, the report is fine)
> ./gradlew coverageReport
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:coverageReport'.
> Unable to read execution data file app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33(AVD) - 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
Digging into the stack trace:
Caused by: : Unable to read execution data file app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33(AVD) - 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
at org.jacoco.ant.ReportTask.loadExecutionData(ReportTask.java:518)
...
Caused by: java.io.IOException: Unknown block type 3.
at org.jacoco.core.data.ExecutionDataReader.readBlock(ExecutionDataReader.java:119)
at org.jacoco.core.data.ExecutionDataReader.read(ExecutionDataReader.java:93)
at org.jacoco.core.tools.ExecFileLoader.load(ExecFileLoader.java:60)
at org.jacoco.ant.ReportTask.loadExecutionData(ReportTask.java:516)
I've seen several other numbers in other projects for the unknown block type, but so far only 3 for this minimal example project.
MD5 sums are the same for the .ec files on and off the device:
> adb shell md5sum /data/media/0/googletest/internal_use/data/data/com.example.coverage/coverage_data/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
89c6b7ac8ad27d4d2f19dce0ac47f028 /data/media/0/googletest/internal_use/data/data/com.example.coverage/coverage_data/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
> md5sum app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33\(AVD\)\ -\ 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
89c6b7ac8ad27d4d2f19dce0ac47f028 app/build/outputs/code_coverage/debugAndroidTest/connected/Nexus_S_API_33(AVD) - 13/com.example.coverage.ExampleInstrumentedTest#useAppContext.ec
Re-running the tests will generally clear the issue on this project. On a larger project, several tests fail like this on each run - different tests each time, though apparently some more than others. It doesn't appear to be linked to the running time of the test.
I tried different versions of:
Gradle (7.4, 7.5, 8.0-rc-1, 8.0-rc-2)
AGP (7.4, 8.1.0-alpha01)
Android Studio (Eel, Giraffe)
emulator SDK version (27, 31, 33)
with the same failing on each.
Syncing with Gradle files and cleaning/rebuilding don't help, and I've seen this happen on the first run of a new project.
I can see that:
Gradle support for Android lags (the new JaCoCo aggregate report plugin is explicitly not supported on Android)
Gradle's had and fixed some similar issues with JaCoCo in recent releases (e.g. https://github.com/gradle/gradle/issues/20532)
a similar issue's been seen with JaCoCo in other contexts (e.g. JaCoco MVN unknown block type which suggests the JVM's being hard-killed between tests)
Turning off clearPackageData doesn't stop these failures.
I was expecting code coverage of instrumented tests to be a core tool in my development process. So far it looks like either this error is a "me" problem, or Android devs don't see much value in having this working reliably. Any insights into why it's not that valuable or can be easily replaced would be as welcome as a fix.

Android Github action with Gradle Managed Device

I try to make a CI test with Gradle Managed Device and Github action. I made several attempts, but I mostly run into
Execution failed for task ':app:nexusOneApi30Setup'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.ManagedDeviceSetupTask$ManagedDeviceSetupRunnable
> java.lang.IllegalStateException: Gradle was not able to complete device setup for: dev30_aosp_atd_x86_Nexus_One
This could be due to having insufficient resources to provision the number of
devices requested. Try running the test again and request fewer devices or
fewer shards.
As source I use https://github.com/android/testing-samples/tree/main/ui/espresso/ScreenshotSample in my fork which works local properly

Re-run failed android tests

Is there a way to run only the failed set of tests on Android using Gradle?
At the moment, I run my tests as follows.
./gradle connectedDebugAndroidTest
There are tests that occasionally fail due to environment issues which are difficult to control and what I would like to do is be able to only run those failed tests and merge the result with the previous test results.
So for example, if I have 100 tests and 90 succeed, I would like to re-run the failing 10 tests. If those 10 pass the second time around, I would like to merge those results with the original test run.
It looks like this has been discussed several times for Gradle but there doesn't seem to be a solution yet.
https://github.com/gradle/gradle/issues/4068
https://github.com/gradle/gradle/issues/4450
https://github.com/gradle/gradle/issues/1283
Thanks!
The reason they don't have a way to only rerun failed tests is because it screws up the way Gradle currently works. This happens because on the first run, Gradle knows 90 tests passed. If you update the code, and then rerun only the 10 failed tests (using this new option you want them to add), then Gradle would think that all the tests have passed. However, this isn't the case because the tests which previously passed might've broken from the update which fixed the failing tests.
Despite this, the problem has been solved. Gradle reruns failed tests first, and provides a --fail-fast flag for the test task. This effectively does what you want (i.e., only reruns failed tests).
If you want to automatically rerun failed tests as part of the same build in which they failed, and succeed the build if they succeed on retry, you can use the Test Retry Gradle plugin. This will rerun each failed test a certain number of times, with the option of failing the build if too many failures have occurred overall.
plugins {
id 'org.gradle.test-retry' version '1.2.0'
}
test {
retry {
maxRetries = 3
maxFailures = 20 // Optional attribute
}
}

Jenkins failing robolectric test cases...!

I am trying to build my android project on Jenkins 2.0 server on Ubuntu machine.
I am running the following commands for that purpose:-
./gradlew clean (this is working fine)
./gradlew build (this is failing random number of test cases)
However I also install Jenkins 2.0 on my Windows 7 machine and run the same commands as above, and it was passing all test cases every time. I am not understanding what is wrong with that.
I did lot of debugging but could not find any solution, please help me to get rid out of this thing...!
This is my 34th build log on Jenkins
testPreCondition FAILED
java.lang.NullPointerException at ConfigurationFragmentTest.java:36
handleBackButtonPressing FAILED
java.lang.NullPointerException at ConfigurationFragmentTest.java:36
48 tests completed, 2 failed
:app:testDebugUnitTest FAILED
This is my 35th build log on Jenkins without making any code changes
> handleBackButtonPressing FAILED
java.lang.NullPointerException at ConfigurationFragmentTest.java:36
> testPreCondition FAILED
java.lang.NullPointerException at ConfigurationFragmentTest.java:36
> testPreconditions FAILED
java.lang.NullPointerException at UpdateTabFragmentTest.java:30
> testPreconditions FAILED
java.lang.NullPointerException at ServiceTabFragmentTest.java:29
> testPreConditionIsNotNull FAILED
java.lang.NullPointerException at HomeActivityTest.java:63
48 tests completed, 5 failed
:app:testDebugUnitTest FAILED
You should check the Jenkins console output for something like
"WARNING: No manifest file found " in the console output.
Those NPEs are typical for missing resources.
The most common source for failing robolectric builds on different environmnets is probably robolectric not beeing able to load any resources.
Since robolectric needs to know where your Android Manifest is, you may have to provide a extra robolectric.properties for the build
http://robolectric.org/configuring/

Gradle in Android Studio 0.44 can't find process on path to run in an Exec Type task

I used to have the following gradle build task:
task buildWebApp(type: Exec) {
executable = Os.isFamily(Os.FAMILY_WINDOWS) ? "grunt.cmd" : "grunt"
args = ["build"]
}
This would pick the appropriate grunt command and run it with the argument "build".
This worked without any kind of issue
I've just tried this in Android Studio 0.4, using Gradle 1.9 and it's no longer working. Instead I get the following error:
Execution failed for task ':BrowserPages:buildWebApp'.
A problem occurred starting process 'command 'grunt''
Normally at this point I would debug with gradlew, but running the following command, throws no errors:
$ ./gradlew buildWebApp
I've also tried running the full task list to still not find any problems.
The way this is executed is from my main build.gradle file with this dependency
copyWebApplication.dependsOn ':BrowserPages:buildWebApp'
Anyone have any ideas?
I've tried to run executable = "node" with arg = ["-v"] and get the same error where it can't find node. Node is globally accessible on my terminal, so I can only assume that the command is being run in a different environment to the terminal. There is the option for setting the environment but I can't find any examples of how it should be used.
Try using a fully-qualified path to the grunt executable. Perhaps something in the path has changed between Android Studio/Gradle/Android Plugin versions.

Categories

Resources