Tips those may help your Android project from failing test on CircleCI
As you may notice, in my previous blog entry, I mentioned CircleCI,
one of many continuous integration services allowing your projects be
built and tested automatically on predefined environments.
In this post I will give some tips to increase the chance to run successfully and pass test on CircleCI.
- CircleCI needs a file named circle.yml put in the root directory of your project, in which you write commands to be executed on CircleCI.
- In common, the process is like: CircleCI first created a virtual machine, then it pulls your code from your repository and sets up the environment, finally it runs the tests. Particularly, CircleCI starts an emulator in the virtual machine they creates (sounds VM in another VM, VM-ception), and uses the Gradle wrapper to run Gradle tasks for testing purpose.
- Remember, the emulator on CircleCI is super-weak.
- Have a quick look (or slow look if you are careful) here and here.
-no-audio -no-skin
That’s why we are setting the background: true attribute on the emulator command. This way, we kick off the emulator and can get back to building.
Also, adding parallel: true tells circle that the command should be run in parallel on all test machines
-netdelay none -netspeed full
Now the emulator command looks like:
test:
override:
- emulator -avd circleci-android22 -netdelay none -netspeed full -no-audio -no-skin:
background: true
parallel: true
project.ext.preDexLibs = !project.hasProperty('disablePreDex')
subprojects {
project.plugins.whenPluginAdded { plugin ->
if ("com.android.build.gradle.AppPlugin".equals(plugin.class.name)) {
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
} else if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) {
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
}
}
}
Then add the option -PdisablePreDex in your command that run tests.
- ./gradlew test -PdisablePreDex
./gradlew test -PdisablePreDex took more than 10 minutes since last output
Add timeout to the command that run your tests (in seconds):
- ./gradlew test -PdisablePreDex:
timeout: 2400
com.android.builder.testing.api.TestException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.ShellCommandUnresponsiveException
Set ADB_INSTALL_TIME_OUT to an amount of time (in minutes) that satisfies your need as:
machine:
environment:
ADB_INSTALL_TIMEOUT : 20
in your circle.yml file.
If it doesn't work, add this in your build.gradle:
com.android.ddmlib.DdmPreferences.setTimeOut(600000)
If it's still not working, add adbOptions in build.gradle:
android {
adbOptions {
timeOutInMs 600000
}
}
Thanks to this thread from StackOverFlow I found this solution when I was really helpless.
I thinks these tips are very simple and everyone should know when working with CircleCI. If you know some tips I haven't listed here, please share, I would love to know.
In this post I will give some tips to increase the chance to run successfully and pass test on CircleCI.
Background
If you are not familiar with CircleCI, you may want to read this. There are something involved:- CircleCI needs a file named circle.yml put in the root directory of your project, in which you write commands to be executed on CircleCI.
- In common, the process is like: CircleCI first created a virtual machine, then it pulls your code from your repository and sets up the environment, finally it runs the tests. Particularly, CircleCI starts an emulator in the virtual machine they creates (sounds VM in another VM, VM-ception), and uses the Gradle wrapper to run Gradle tasks for testing purpose.
- Remember, the emulator on CircleCI is super-weak.
- Have a quick look (or slow look if you are careful) here and here.
Here are the tips
Build your emulator
An emulator is started before test part is run, so you need to put the command to create it in that part of the circle.yml fileDisable emulator skin and audio
Do you need these features? If the answer is no, then add these options to emulator create command:-no-audio -no-skin
Start the emulator in background and in parallel
Running the emulator from the terminal is a blocking command. We would have to wait anywhere between 2-7 minutes for the emulator to start and then build the apk...That’s why we are setting the background: true attribute on the emulator command. This way, we kick off the emulator and can get back to building.
Also, adding parallel: true tells circle that the command should be run in parallel on all test machines
Add network options
To add more confidence to your AVD, add options to emulator create command for networking if your tests have to connect to the world.-netdelay none -netspeed full
Now the emulator command looks like:
test:
override:
- emulator -avd circleci-android22 -netdelay none -netspeed full -no-audio -no-skin:
background: true
parallel: true
Disable Predexing
As CircleCI suggests: Add this to your root build.gradle file:project.ext.preDexLibs = !project.hasProperty('disablePreDex')
subprojects {
project.plugins.whenPluginAdded { plugin ->
if ("com.android.build.gradle.AppPlugin".equals(plugin.class.name)) {
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
} else if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) {
project.android.dexOptions.preDexLibraries = rootProject.ext.preDexLibs
}
}
}
Then add the option -PdisablePreDex in your command that run tests.
- ./gradlew test -PdisablePreDex
Set timeouts
Sometimes, you fail test and CircleCI throws a timeout exception. You can fix it by set proper timeouts.Set timeout to the test command
When you get this error from CircleCI:
./gradlew test -PdisablePreDex took more than 10 minutes since last output
Add timeout to the command that run your tests (in seconds):
- ./gradlew test -PdisablePreDex:
timeout: 2400
Set timeout to adb install
When you get this error from CircleCI:com.android.builder.testing.api.TestException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.ShellCommandUnresponsiveException
Set ADB_INSTALL_TIME_OUT to an amount of time (in minutes) that satisfies your need as:
machine:
environment:
ADB_INSTALL_TIMEOUT : 20
in your circle.yml file.
If it doesn't work, add this in your build.gradle:
com.android.ddmlib.DdmPreferences.setTimeOut(600000)
If it's still not working, add adbOptions in build.gradle:
android {
adbOptions {
timeOutInMs 600000
}
}
Thanks to this thread from StackOverFlow I found this solution when I was really helpless.
I thinks these tips are very simple and everyone should know when working with CircleCI. If you know some tips I haven't listed here, please share, I would love to know.
To make this post much more beautiful |
Comments
Post a Comment