Android Command Line Testing with Gradle - android

I have been researching this for multiple days now and dug up some good resources like this user guide. I can also build and install just fine thanks to this article. However, I cannot, for the life of me, figure out how to run my instrumentation tests without having a connected device.
Is it simply not possible to run the tests under app/src/androidTest (where I have most of my tests) without using the command ./gradlew connectedAndroidTest?
Also, I've seen it's recommended to put jUnit tests under app/src/test and Instrumentation tests under the gradle preconfigured app/src/androidTest. Is this a good way to set up the app's tests, even though that means creating two different testing directories?
I'm asking all of this because I'm using a Jenkins CI job to build the Android project upon the code being updated and I'd like Jenkins to run all of my tests along with building the project, but I'd hope I wouldn't have to concern myself with creating some sort of emulator/device for Jenkins to run the tests on (as required by ./gradlew connectedAndroidTest).

Yes, it is the proper way to set up app's test as JUnit tests (in app/src/test) run on JVM and Instrumentation tests run on connected device.
http://developer.android.com/training/testing/unit-testing/instrumented-unit-tests.html
Possible solution - In pre-build step on Jenkins, run emulator/Genymotion from commandline and run all tests with
./gradlew cAT
OR keep the Genymotion/emulator setup running always.
https://www.genymotion.com/#!/

For those who have found this topic same as I and are thinking about running Android from terminal, possibly in CI.
I have been working with CI on GitLab lately. I have figured out a better way without gennymotion, with mere android avd created by avdmanager. New Android Tools are optimized to run from terminal, which can be used in docker images for example.
More info in this tutorial and update the gitlab compose script as below.
image: openjdk:8-jdk
variables: # such as ..
ANDROID_SDK_TOOLS_URL: "https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip" # https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
ANDROID_SDK_VERSION: "26" # 26
ANDROID_BUILD_TOOLS: "26.0.2" # 26.0.1
before_script:
- apt-get --quiet update --yes
- apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
- wget --quiet --output-document=android-tools.zip ${ANDROID_SDK_TOOLS_URL}
- unzip android-tools.zip -d android-sdk-linux
- echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" --verbose # SDK Platform-Tools
- echo y | android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_SDK_VERSION}" --verbose # SDK Platform
- echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" --verbose # SDK Build-Tools
- echo y | android-sdk-linux/tools/bin/sdkmanager "extras;android;m2repository" --verbose # Support Repository
- echo y | android-sdk-linux/tools/bin/sdkmanager "extras;google;m2repository" --verbose # Google Repository
- echo y | android-sdk-linux/tools/bin/sdkmanager "extras;google;google_play_services" --verbose # Google Play services
- export ANDROID_HOME=$PWD/android-sdk-linux
- export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
- chmod +x ./gradlew
stages:
- build
- test
build:
stage: build
script:
- ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/
unitTests:
stage: test
script:
- ./gradlew test
functionalTests:
stage: test
script:
- wget --quiet --output-document=android-wait-for-emulator https://raw.githubusercontent.com/travis-ci/travis-cookbooks/0f497eb71291b52a703143c5cd63a217c8766dc9/community-cookbooks/android-sdk/files/default/android-wait-for-emulator
- chmod +x android-wait-for-emulator
- echo y | android-sdk-linux/tools/bin/sdkmanager --verbose --update
- echo y | android-sdk-linux/tools/bin/sdkmanager --verbose "system-images;android-${ANDROID_SDK_VERSION};google_apis;x86"
- echo no | android-sdk-linux/tools/bin/avdmanager create avd -n test -k "system-images;android-${ANDROID_SDK_VERSION};google_apis;x86" # no custom HW profile
- android-sdk-linux/tools/emulator -avd test -no-window -no-audio & # run headless "test" AVD
- ./android-wait-for-emulator # if ran fast enough it will catch cange of state on Boot Animation ~ init.svc.bootanim
- adb shell input keyevent 82 # some dummy input
- ./gradlew cAT

Related

Emulator: ERROR: detected a hanging thread 'QEMU1 main loop'. No response for 105001 ms

I use Gitlab CI for continuous integration. After every commit I have 3 jobs in the pipeline: debug, unitTests and instrumentedTests. But now instrumented tests failed because of the timeout. I added my gitlab-ci.yml file below
I've already tried downgrade android sdk versions, but no luck at all. Maybe there are some commands for yml-file that could fix the problem.
Also maybe somebody knows how to make all tests not failed for EMULATOR_VERSION > 22. 24 or higher never worked at all.
image: openjdk:8-jdk
variables:
ANDROID_COMPILE_SDK: "28"
ANDROID_BUILD_TOOLS: "28.0.3"
ANDROID_SDK_TOOLS: "4333796" # from https://developer.android.com/studio/#command-tools
EMULATOR_VERSION: "22"
before_script:
- apt-get --quiet update --yes
- apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
- wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip
- unzip -d android-sdk-linux android-sdk.zip
- echo y | android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
- echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" >/dev/null
- echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null
- export ANDROID_HOME=$PWD/android-sdk-linux
- export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
- chmod +x ./gradlew
# temporarily disable checking for EPIPE error and use yes to accept all licenses
- set +o pipefail
- yes | android-sdk-linux/tools/bin/sdkmanager --licenses
- set -o pipefail
stages:
- build
- test
assembleDebug:
stage: build
script:
- ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/
unitTests:
stage: test
script:
- ./gradlew test
instrumentedTests:
stage: test
script:
- wget --quiet --output-document=android-wait-for-emulator https://raw.githubusercontent.com/travis-ci/travis-cookbooks/0f497eb71291b52a703143c5cd63a217c8766dc9/community-cookbooks/android-sdk/files/default/android-wait-for-emulator
- chmod +x android-wait-for-emulator
- android-sdk-linux/tools/bin/sdkmanager --update > update.log
- android-sdk-linux/tools/bin/sdkmanager "platform-tools" "emulator" "system-images;android-${EMULATOR_VERSION};default;armeabi-v7a" > installEmulator.log
- echo no | android-sdk-linux/tools/bin/avdmanager create avd -n test -k "system-images;android-${EMULATOR_VERSION};default;armeabi-v7a"
- android-sdk-linux/emulator/emulator -avd test -no-window -no-audio &
- ./android-wait-for-emulator
- adb shell input keyevent 82
- ./gradlew connectedCheck
There are following factors:
looks like google dropped support of qemu engine and only ranchu is supported for now
sdk was partially updated but there are bugs in update process
While qemu is no more supported this concrete bug with hanging seems wouldn't fixed ever.
For switch to ranchu environment:
avoid using *default* platform for avd's, prefer *google-api*'s one (while ranchu kernel is missed in default platforms)
update sdk with --channel=4
Just in case it helped me.

Travis CI cant find our gradlew file

We are trying to integrate our android app with travis CI. But it always fails with cannot access ‘gradlew’: No such file or directory. We can run the gradlew script from our local computer and the file is tracked by git. What can the problem be?
Our .travis.yml file:
sudo: false
language: android
jdk: oraclejdk8
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
- $HOME/.android/build-cache
before_script:
- cd TreasurePleasure
- echo no | android create avd --force -n test -t "android-"$ANDROID_EMULATOR_LEVEL --abi $ANDROID_ABI --tag $ANDROID_TAG
- emulator -avd test -no-window &
- android-wait-for-emulator
- adb shell input keyevent 82 &
android:
components:
- tools
- tools # Running this twice get's the latest build tools (https://github.com/codepath/android_guides/wiki/Setting-up-Travis-CI)
- platform-tools
- build-tools-27.0.3
- android-27
- android-$ANDROID_EMULATOR_LEVEL
- sys-img-armeabi-v7a-google_apis-$ANDROID_EMULATOR_LEVEL
licenses:
- '.+'
env:
global:
- ANDROID_API_LEVEL=27
- ANDROID_EMULATOR_LEVEL=21
- ANDROID_BUILD_TOOLS_VERSION=27.0.3
- ANDROID_ABI=armeabi-v7a
- ANDROID_TAG=google_apis
- ADB_INSTALL_TIMEOUT=20
before_install:
- chmod +x gradlew
- yes | sdkmanager "platforms;android-27"
script:
- "./gradlew clean build connectedCheck -PdisablePreDex --stacktrace"
# run tests against the emulator
- ./gradlew connectedAndroidTest
# run tests against the JVM
- ./gradlew test
Most of this is copy paste since this is the first project for us that are using Travis CI.
Our error:
This is how it works in my scripts:
before_script:
- cd ${TRAVIS_BUILD_DIR}/TreasurePleasure
- chmod +x ./gradlew
script: "./gradlew assemble"

Travis CI android emulator can't be created with avdmanager

I want to build and test an Android app using an emulator in Travis CI.
On my local machine I can create emulator with both android and avdmanager tools, examples:
echo no | android create avd --force --name test01 --package 'system-images;android-27;google_apis_playstore;x86'
echo no | avdmanager create avd --force --name test02 --package 'system-images;android-27;google_apis_playstore;x86'
But on Travis there's no avdmanager in $ANDROID_HOME/tools/bin
When I tried to create emulator with android tool (which isn't desired because it's deprecated) it turned out that it's different from version installed on my mac and requires different parameters
My .travis.yml file (vars and build steps removed for clarity):
sudo: true
os: linux
dist: trusty
language: android
android:
components:
- build-tools-26.0.2
- android-26
before_script:
- echo no | android create avd --force --name test --package 'system-images;android-27;google_apis_playstore;x86'
#- echo no | avdmanager create avd --force --name test --package 'system-images;android-27;google_apis_playstore;x86'
script:
- echo "DEBUG searching for avdmanager" && ls -lAp $ANDROID_HOME/tools/bin
So could you please advice how should I create Android emulator in Travis CI?
After playing around the official ways, the simplest way I found to launch one emulator on travis has at least this in travis.xml
before_install:
# Install SDK license so Android Gradle plugin can install deps.
- mkdir "$ANDROID_HOME/licenses" || true
- echo "d56f5187479451eabf01fb78af6dfcb131a6481e" >> "$ANDROID_HOME/licenses/android-sdk-license"
# Install the rest of tools (e.g. avdmanager)
- sdkmanager tools
# Install the system image.
- sdkmanager "system-images;android-24;default;armeabi-v7a"
# Create and start emulator for the script. Meant to race the install task.
- echo no | avdmanager create avd --force -n emulatorApi24 -k "system-images;android-24;default;armeabi-v7a"
- $ANDROID_HOME/emulator/emulator -avd emulatorApi24 -no-audio -no-window &
before_script:
- android-wait-for-emulator
# Disable animations
- adb shell settings put global window_animation_scale 0 &
- adb shell settings put global transition_animation_scale 0 &
- adb shell settings put global animator_duration_scale 0 &
- adb shell input keyevent 82 &
script: ./gradlew connectedAndroidTest # Run emulator tests
Now my travis build takes 20 minutes :D
As a reference, a good place to check a working example is the U+2020 project.

Docker GitLab Error running Android Emulator: Cannot decide host bitness. 32 bits assumed

I am trying to automate Android Builds and Tests. The instrumentation test is not working because I get the following error while starting the android emulator in the Docker Runner:
Running with gitlab-ci-multi-runner 9.4.2 (6d06f2e) ...
Using Docker executor with image kmindi/android-ci:latest ...
...
$ chmod +x ./gradlew
$ echo no | avdmanager -v create avd --force --name test --abi google_apis/x86_64 --package 'system-images;android-25;google_apis;x86_64'
Do you wish to create a custom hardware profile? [no] $ export SHELL=/bin/bash && echo "no" | emulator -avd test -noaudio -no-window -gpu off -verbose -qemu
sh: 1: file: not found
sh: 1: file: not found
WARNING: Cannot decide host bitness because $SHELL is not properly defined; 32 bits assumed.
ERROR: 32-bit Linux Android emulator binaries are DEPRECATED, to use them
you will have to do at least one of the following:
- Use the '-force-32bit' option when invoking 'emulator'.
- Set ANDROID_EMULATOR_FORCE_32BIT to 'true' in your environment.
Either one will allow you to use the 32-bit binaries, but please be
aware that these will disappear in a future Android SDK release.
Consider moving to a 64-bit Linux system before that happens.
ERROR: Job failed: exit code 1
I created the following Dockerfile (https://hub.docker.com/r/kmindi/android-ci/)
FROM openjdk:8-jdk
ENV ANDROID_BUILD_TOOLS "26.0.1"
ENV ANDROID_SDK_TOOLS "25.2.5"
ENV ANDROID_HOME "/android-sdk"
ENV PATH=$PATH:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools
# Prepare dependencies
RUN mkdir $ANDROID_HOME \
&& apt-get update --yes \
&& apt-get install --yes wget tar unzip lib32stdc++6 lib32z1 libqt5widgets5 expect \
&& apt-get clean \
&& rm -fr /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Install sdk tools
RUN wget -O android-sdk.zip https://dl.google.com/android/repository/tools_r${ANDROID_SDK_TOOLS}-linux.zip \
&& unzip -q android-sdk.zip -d $ANDROID_HOME \
&& rm android-sdk.zip
# Workaround for
# Warning: File /root/.android/repositories.cfg could not be loaded.
RUN mkdir /root/.android \
&& touch /root/.android/repositories.cfg
# Workaround for host bitness error with android emulator
# https://stackoverflow.com/a/37604675/455578
RUN mv /bin/sh /bin/sh.backup \
&& cp /bin/bash /bin/sh
# Add tools from travis
ADD https://raw.githubusercontent.com/travis-ci/travis-cookbooks/ca800a93071a603745a724531c425a41493e70ff/community-cookbooks/android-sdk/files/default/android-wait-for-emulator /usr/local/bin/android-wait-for-emulator
RUN chmod +x /usr/local/bin/android-wait-for-emulator
# Add own tools
COPY assure_emulator_awake.sh /usr/local/bin/assure_emulator_awake.sh
RUN chmod +x /usr/local/bin/assure_emulator_awake.sh
# Update platform and build tools
RUN echo "y" | sdkmanager "tools" "platform-tools" "build-tools;${ANDROID_BUILD_TOOLS}"
# Update SDKs
RUN echo "y" | sdkmanager "platforms;android-26" "platforms;android-25"
# Update emulators
RUN echo "y" | sdkmanager "system-images;android-25;google_apis;x86_64"
# Update extra
RUN echo "y" | sdkmanager "extras;android;m2repository" "extras;google;m2repository" "extras;google;google_play_services"
# Constraint Layout
RUN echo "y" | sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2"
RUN echo "y" | sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.2"
In GitLab I use the following .gitlab-ci.yml:
image: kmindi/android-ci:latest
variables:
ANDROID_COMPILE_SDK: "25"
before_script:
- chmod +x ./gradlew
stages:
- build
- test
build:
stage: build
script:
- ./gradlew assembleDebug
artifacts:
name: "App_{$CI_BUILD_ID}"
expire_in: 1 week
paths:
- "app/build/outputs/apk/**/*.apk"
except:
- tags
test:unit:
stage: test
script:
- ./gradlew test jacoco
artifacts:
name: "tests-unit-${CI_BUILD_NAME}_${CI_COMMIT_REF_NAME}_${CI_BUILD_REF}"
expire_in: 1 week
paths:
- "**/build/reports/**"
test:instrumentation:25:
stage: test
script:
- echo no | avdmanager -v create avd --force --name test --abi google_apis/x86_64 --package 'system-images;android-25;google_apis;x86_64'
- export SHELL=/bin/bash && echo "no" | emulator -avd test -noaudio -no-window -gpu off -verbose -qemu &
- adb wait-for-device
- android-wait-for-emulator
- export TERM=${TERM:-dumb}
- assure_emulator_awake.sh "./gradlew cAT"
- ./gardlew createDebugCoverageReport
artifacts:
name: "tests-instrumentation-${ANDROID_COMPILE_SDK}-${CI_BUILD_NAME}"
expire_in: 1 week
paths:
- "**/build/reports/**"
The workaround proposed in https://stackoverflow.com/a/37604675/455578 (chaning of bash/sh) is not working (applied in the Dockerfile). Also setting the SHELL variable does not help. If I use emulator64-x86 instead of emulator I get the error command not found.
What am I missing?
Do I have to install other packages via apt?
Maybe it originates in the used openjdk-8 / debian stretch docker image?
Thanks :)
With SDK Revision 25.3.0 (March 2017) emulator was released separately from the SDK Tools (https://developer.android.com/studio/releases/emulator.html#25-3).
Practically it means that now there is a new ${ANDROID_HOME}/emulator folder which you have to add to PATH. (NOTE: it has to be added before tools folder, because for whatever reason old tools/emulator binary is still there). Example:
ENV PATH ${ANDROID_HOME}/emulator:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools:${PATH}

CircleCI Trouble with gradlew in another folder

I have a problem with CircleCI that I can not get to work because my gradlew file is not in the root of my repository. As my depot is deprived here is a summary of his architectures:
root
-----> app_folder
------------> some folders
------------> some files
------------> gradlew
------> some files and folders
------> circle.yml
I tried to go into the app_folder folder using the cd command and change the path variable but nothing of it worked
circle.yml
#
# Build configuration for Circle CI
#
machine:
environment:
PATH: "~/$CIRCLE_PROJECT_REPONAME/app_folder:$PATH"
ANDROID_HOME: /usr/local/android-sdk-linux
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
_JAVA_OPTIONS: "-Xms512m -Xmx1024m"
ADB_INSTALL_TIMEOUT: "10"
ANDROID_API_LEVEL: 25
ANDROID_BUILD_TOOLS_VERSION: 25.0.2
java:
version: oraclejdk7
dependencies:
cache_directories:
- ~/.gradle
- ~/.android
- /usr/local/android-sdk-linux/extras
pre:
- if [ ! -d "$ANDROID_HOME/tools" ]; then echo y | android update sdk --no-ui --all --filter "tools"; fi
- if [ ! -d "$ANDROID_HOME/platforms/android-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "android-$ANDROID_API_LEVEL"; fi
- if [ ! -d "$ANDROID_HOME/build-tools/$ANDROID_BUILD_TOOLS_VERSION" ]; then echo y | android update sdk --no-ui --all --filter "build-tools-$ANDROID_BUILD_TOOLS_VERSION"; fi
- if [ ! -d "$ANDROID_HOME/add-ons/addon-google_apis-google-$ANDROID_API_LEVEL" ]; then echo y | android update sdk --no-ui --all --filter "addon-google_apis-google-$ANDROID_API_LEVEL"; fi
- echo y | android update sdk --no-ui --all --filter "extra-google-m2repository"
- echo y | android update sdk --no-ui --all --filter "extra-google-google_play_services"
- echo y | android update sdk --no-ui --all --filter "extra-android-m2repository"
test:
override:
# start the emulator
- emulator -avd circleci-android24 -no-audio -no-window:
background: true
parallel: true
# wait for it to have booted
- circle-android wait-for-boot
# unlock the emulator screen
- sleep 30
- adb shell input keyevent 82
# run tests against the emulator.
- echo $PATH
- cd app_folder && .\gradlew connectedAndroidTest -PdisablePreDex
- .\\app_folder\\gradlew connectedAndroidTest -PdisablePreDex
- .\app_folder\\gradlew connectedAndroidTest -PdisablePreDex
- .\gradlew connectedAndroidTest -PdisablePreDex ~/github_name/app_folder
# copy the build outputs to artifacts
- cp -r app_folder/app/build/outputs $CIRCLE_ARTIFACTS
# copy the test results to the test results directory.
- cp -r app_folder/app/build/outputs/androidTest-results/* $CIRCLE_TEST_REPORTS
You just need to add this on the top :
general:
build_dir: your_folder
There's two options here. The quickest is to specify a custom build directory. Using your example, this would be:
general:
build_dir: app_folder
This is because per CircleCI Docs:
CircleCI will run its inference as well as all build commands from
that directory.
The second option would be to not rely on CircleCI's Inference commands at all and instead run everything, like Gradle yourself. You're already overriding the test phase, so you'd need to override the dependencies phase as well and run gradle dependencies yourself.
For example:
dependencies:
override:
- gradle --project-dir app_folder dependencies
-Ricardo N Feliciano
Developer Evangelist, CircleCI

Categories

Resources