Merge branch 'release-1.1' into patch-2

This commit is contained in:
Greener Chen 2018-07-05 23:34:22 +08:00 committed by GitHub
commit 7e7d12e4e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 524 additions and 118 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
*.mp4 filter=lfs diff=lfs merge=lfs -text

3
.gitignore vendored
View file

@ -7,6 +7,3 @@
coverage.xml coverage.xml
xunit.xml xunit.xml
coverage/* coverage/*
# Video
video*

View file

@ -10,6 +10,10 @@
Docker-Android is a docker image built to be used for everything related to mobile website testing and Android project. Docker-Android is a docker image built to be used for everything related to mobile website testing and Android project.
<p align="center">
<a href="https://youtu.be/pQdpjuYwvp8"><img src="./images/appiumconf2018.png" alt="Appium Conference 2018" width="600"></a>
</p>
Emulator - Samsung Device | Emulator - Nexus Device | Real Device Emulator - Samsung Device | Emulator - Nexus Device | Real Device
:---------------------------:|:---------------------------:|:---------------------------: :---------------------------:|:---------------------------:|:---------------------------:
![][emulator samsung] |![][emulator nexus] |![][real device] ![][emulator samsung] |![][emulator nexus] |![][real device]
@ -50,6 +54,7 @@ List of Docker images
|OSX / Windows|7.0|24|butomo1989/docker-android-arm-7.0|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-arm-7.0.svg)](https://microbadger.com/images/butomo1989/docker-android-arm-7.0 "Get your own image badge on microbadger.com")| |OSX / Windows|7.0|24|butomo1989/docker-android-arm-7.0|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-arm-7.0.svg)](https://microbadger.com/images/butomo1989/docker-android-arm-7.0 "Get your own image badge on microbadger.com")|
|OSX / Windows|7.1.1|25|butomo1989/docker-android-arm-7.1.1|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-arm-7.1.1.svg)](https://microbadger.com/images/butomo1989/docker-android-arm-7.1.1 "Get your own image badge on microbadger.com")| |OSX / Windows|7.1.1|25|butomo1989/docker-android-arm-7.1.1|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-arm-7.1.1.svg)](https://microbadger.com/images/butomo1989/docker-android-arm-7.1.1 "Get your own image badge on microbadger.com")|
|All |-|-|butomo1989/docker-android-real-device|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-real-device.svg)](https://microbadger.com/images/butomo1989/docker-android-real-device "Get your own image badge on microbadger.com")| |All |-|-|butomo1989/docker-android-real-device|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-real-device.svg)](https://microbadger.com/images/butomo1989/docker-android-real-device "Get your own image badge on microbadger.com")|
|Linux|All|All|butomo1989/docker-android-genymotion|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-genymotion.svg)](https://microbadger.com/images/butomo1989/docker-android-genymotion "Get your own image badge on microbadger.com")|
List of Devices List of Devices
--------------- ---------------
@ -100,17 +105,17 @@ Quick Start
Run Appium Server Run Appium Server
----------------- -----------------
Appium is automation test framework to test mobile website and mobile application, including android. To be able to use appium, you need to run appium-server. You run appium server inside docker-android container by ***opening port 4723*** and ***passing an environment variable APPIUM=TRUE***. Appium is automation test framework to test mobile website and mobile application, including android. To be able to use appium, you need to run appium-server. You run appium server inside docker-android container by ***opening port 4723*** and ***passing an environment variable APPIUM=true***.
```bash ```bash
docker run --privileged -d -p 6080:6080 -p 5554:5554 -p 5555:5555 -p 4723:4723 -e DEVICE="Samsung Galaxy S6" -e APPIUM=True --name android-container butomo1989/docker-android-x86-7.1.1 docker run --privileged -d -p 6080:6080 -p 5554:5554 -p 5555:5555 -p 4723:4723 -e DEVICE="Samsung Galaxy S6" -e APPIUM=true --name android-container butomo1989/docker-android-x86-7.1.1
``` ```
### Connect to Selenium Grid ### Connect to Selenium Grid
It is also possible to connect appium server that run inside docker-android with selenium grid by passing following environment variables: It is also possible to connect appium server that run inside docker-android with selenium grid by passing following environment variables:
- CONNECT\_TO\_GRID=True - CONNECT\_TO\_GRID=true
- APPIUM_HOST="\<host\_ip\_address>" - APPIUM_HOST="\<host\_ip\_address>"
- APPIUM_PORT=\<port\_number> - APPIUM_PORT=\<port\_number>
- SELENIUM_HOST="\<host\_ip\_address>" - SELENIUM_HOST="\<host\_ip\_address>"
@ -118,10 +123,10 @@ It is also possible to connect appium server that run inside docker-android with
To run tests for mobile browser, following parameter can be passed: To run tests for mobile browser, following parameter can be passed:
- MOBILE\_WEB\_TEST=True - MOBILE\_WEB\_TEST=true
```bash ```bash
docker run --privileged -d -p 6080:6080 -p 4723:4723 -p 5554:5554 -p 5555:5555 -e DEVICE="Samsung Galaxy S6" -e APPIUM=True -e CONNECT_TO_GRID=True -e APPIUM_HOST="127.0.0.1" -e APPIUM_PORT=4723 -e SELENIUM_HOST="172.17.0.1" -e SELENIUM_PORT=4444 -e MOBILE_WEB_TEST=True --name android-container butomo1989/docker-android-x86-7.1.1 docker run --privileged -d -p 6080:6080 -p 4723:4723 -p 5554:5554 -p 5555:5555 -e DEVICE="Samsung Galaxy S6" -e APPIUM=true -e CONNECT_TO_GRID=true -e APPIUM_HOST="127.0.0.1" -e APPIUM_PORT=4723 -e SELENIUM_HOST="172.17.0.1" -e SELENIUM_PORT=4444 -e MOBILE_WEB_TEST=true --name android-container butomo1989/docker-android-x86-7.1.1
``` ```
### Share Volume ### Share Volume
@ -129,7 +134,7 @@ docker run --privileged -d -p 6080:6080 -p 4723:4723 -p 5554:5554 -p 5555:5555 -
If you want to use appium to test UI of your android application, you need to share volume where the APK is located to folder ***/root/tmp***. If you want to use appium to test UI of your android application, you need to share volume where the APK is located to folder ***/root/tmp***.
```bash ```bash
docker run --privileged -d -p 6080:6080 -p 4723:4723 -p 5554:5554 -p 5555:5555 -v $PWD/example/sample_apk:/root/tmp -e DEVICE="Nexus 5" -e APPIUM=True -e CONNECT_TO_GRID=True -e APPIUM_HOST="127.0.0.1" -e APPIUM_PORT=4723 -e SELENIUM_HOST="172.17.0.1" -e SELENIUM_PORT=4444 --name android-container butomo1989/docker-android-x86-7.1.1 docker run --privileged -d -p 6080:6080 -p 4723:4723 -p 5554:5554 -p 5555:5555 -v $PWD/example/sample_apk:/root/tmp -e DEVICE="Nexus 5" -e APPIUM=true -e CONNECT_TO_GRID=true -e APPIUM_HOST="127.0.0.1" -e APPIUM_PORT=4723 -e SELENIUM_HOST="172.17.0.1" -e SELENIUM_PORT=4444 --name android-container butomo1989/docker-android-x86-7.1.1
``` ```
### Video Recording ### Video Recording
@ -163,6 +168,45 @@ docker-android can be used for building Android project and executing its unit t
docker run -it --rm -v $PWD/android-testing/ui/espresso/BasicSample:/root/tmp butomo1989/docker-android-x86-7.1.1 tmp/gradlew build docker run -it --rm -v $PWD/android-testing/ui/espresso/BasicSample:/root/tmp butomo1989/docker-android-x86-7.1.1 tmp/gradlew build
``` ```
Proxy
-----
You can enable proxy inside container by passing following environment variables:
- HTTP_PROXY="\<docker\_bridge\_ip\_address>"
- HTTPS_PROXY="\<docker\_bridge\_ip\_address>"
- NO_PROXY="localhost"
Relaxed Security
-----
Pass environment variable RELAXED_SECURITY=true to disable additional security check to use some advanced features.
Genymotion
----------
![Genymotion](images/logo_genymotion.png)
Docker-Android supports [Genymotion Cloud].
You can easily scale your Appium tests on Genymotion Android virtual devices in the cloud.
Use [device.json] to define the device to start. You can specify the port on which the device will start so you don't need to change the device name in your tests every time you need to run those tests. Then run following command
```bash
export USER="xxx"
export PASS="xxx"
export LICENSE="xxx"
docker run -it --rm -p 4723:4723 -v $PWD/genymotion/example/sample_devices:/root/tmp -e USER=$USER -e PASS=$PASS -e LICENSE=$LICENSE butomo1989/docker-android-genymotion
```
You can also use [this docker-compose file].
<p align="center">
<a href="https://youtu.be/jXhUEyaVeMY"><img src="./images/Genymotion_cloud.png" alt="Docker-Android supports Genymotion Cloud" width="600"></a>
</p>
Control android emulator outside container Control android emulator outside container
------------------------------------------ ------------------------------------------
@ -223,12 +267,12 @@ $ brew install docker-machine-parallels
2. Create a virtual machine for running docker images based on the virtual machine tool you use 2. Create a virtual machine for running docker images based on the virtual machine tool you use
Create a virtual machine of VMWare Fusion 2.1. Create a virtual machine of VMWare Fusion
```bash ```bash
$ docker-machine create --driver=vmwarefusion vmware-dev $ docker-machine create --driver=vmwarefusion vmware-dev
``` ```
Create a virtual machine of Parallels Desktop 2.2. Create a virtual machine of Parallels Desktop
```bash ```bash
$ docker-machine create --driver=parallels prl-dev $ docker-machine create --driver=parallels prl-dev
``` ```
@ -237,47 +281,46 @@ This utility `docker-machine-parallels` will fetch boot2docker.iso to create a v
3. Setup the virtual machine for nested virtualization support 3. Setup the virtual machine for nested virtualization support
Shutdown the vm by running the command below in the boot2docker vm before you setup it. 3.1. Shutdown the vm by running the command below in the boot2docker vm before you setup it.
```bash ```bash
# shutdown -h now # shutdown -h now
``` ```
If you use VMWare Fusion, go to menu bar > Vitual Machine > Settings > Processors and Memory, expand Advanced options, and select `Enable hypervisor applications in this virtual machine`. If you use VMWare Fusion, go to menu bar > Vitual Machine > Settings > Processors and Memory, expand Advanced options, and select `Enable hypervisor applications in this virtual machine`.
[![Enable nested virtualization for VMWare Fusion](images/vmwarefusion_enable_nested_virtualization.png)] ![Enable nested virtualization for VMWare Fusion](images/vmwarefusion_enable_nested_virtualization.png)
If you use Parallels Desktop, open settings screen of that vm and go to `CPU & Memory` under `hardware` tab, expand Advanced settings and select `Enable nested virtualization`. If you use Parallels Desktop, open settings screen of that vm and go to `CPU & Memory` under `hardware` tab, expand Advanced settings and select `Enable nested virtualization`.
[![Enable nested virtualization for Parallels Desktop](images/parallels_enable_nested_virtualization.png)] ![Enable nested virtualization for Parallels Desktop](images/parallels_enable_nested_virtualization.png)
4. Enable kvm inside virtual machine 4. Enable kvm inside virtual machine
Run as an account other than root to install kvm packages using tce-load. 4.1. Run as an account other than root to install kvm packages using tce-load.
```bash ```bash
# su docker # su docker
$ tce-load -wi kvm $ tce-load -wi kvm
``` ```
Run as root to load kvm module after kvm packages install. 4.2. Run as root to load kvm module after kvm packages install.
```bash ```bash
$ sudo modprobe kvm_intel $ sudo modprobe kvm_intel
``` ```
Check if the kvm device is loaded. 4.3. Check if the kvm device is loaded.
```bash ```bash
$ ls /dev/kvm $ ls /dev/kvm
``` ```
Check if your CPU supports hardware virtualization now 4.4. Check if your CPU supports hardware virtualization now
```bash ```bash
$ egrep -c '(vmx|svm)' /proc/cpuinfo $ egrep -c '(vmx|svm)' /proc/cpuinfo
``` ```
If **0** it means that your CPU doesn't support hardware virtualization. If **0** it means that your CPU doesn't support hardware virtualization.
If **1** or more it does - but you still need to make sure that virtualization is enabled in the BIOS. If **1** or more it does - but you still need to make sure that virtualization is enabled in the BIOS.
5. You may now run a docker container 5. You may now run a docker container
Let's run a docker image for an emulator with x86 processor. 5.1. Let's run a docker image for an emulator with x86 processor.
```bash ```bash
docker run --privileged -d -p 6080:6080 -p 5554:5554 -p 5555:5555 -e DEVICE="Samsung Galaxy S6" --name android-container butomo1989/docker-android-x86-7.1.1 docker run --privileged -d -p 6080:6080 -p 5554:5554 -p 5555:5555 -e DEVICE="Samsung Galaxy S6" --name android-container butomo1989/docker-android-x86-7.1.1
``` ```
@ -307,6 +350,9 @@ Special Thanks
[example of compose file]: <docker-compose.yml> [example of compose file]: <docker-compose.yml>
[docker-compose]: <https://docs.docker.com/compose/install/> [docker-compose]: <https://docs.docker.com/compose/install/>
[1.13.0]: <https://github.com/docker/compose/releases/tag/1.13.0> [1.13.0]: <https://github.com/docker/compose/releases/tag/1.13.0>
[Genymotion Cloud]: <https://www.genymotion.com/cloud/>
[device.json]: <genymotion/example/sample_devices/devices.json>
[this docker-compose file]: <genymotion/example/geny.yml>
[adb_connection]: <images/adb_connection.png> [adb_connection]: <images/adb_connection.png>
[sms]: <images/SMS.png> [sms]: <images/SMS.png>
[gian christanto]: <https://www.linkedin.com/in/gian-christanto-0b398b131/> [gian christanto]: <https://www.linkedin.com/in/gian-christanto-0b398b131/>

View file

@ -6,9 +6,9 @@ version: "2.2"
services: services:
# Selenium hub # Selenium hub
selenium_hub: selenium_hub:
image: selenium/hub:3.11.0-bismuth image: selenium/hub:3.12.0-americium
ports: ports:
- "4444:4444" - 4444:4444
# There is a bug for using appium. Issue: https://github.com/butomo1989/docker-android/issues/73 # There is a bug for using appium. Issue: https://github.com/butomo1989/docker-android/issues/73
# Real devices # Real devices
@ -24,10 +24,10 @@ services:
# - /dev/bus/usb:/dev/bus/usb # - /dev/bus/usb:/dev/bus/usb
# - ~/.android:/root/.android # - ~/.android:/root/.android
# environment: # environment:
# - CONNECT_TO_GRID=True # - CONNECT_TO_GRID=true
# - APPIUM=true # - APPIUM=true
# - SELENIUM_HOST=selenium_hub # - SELENIUM_HOST=selenium_hub
# - AUTO_RECORD=True # - AUTO_RECORD=true
# - BROWSER_NAME=chrome # - BROWSER_NAME=chrome
# Using Appium Docker Android # Using Appium Docker Android
@ -42,7 +42,7 @@ services:
- ~/.android:/root/.android - ~/.android:/root/.android
- $PWD/example/sample_apk:/root/tmp - $PWD/example/sample_apk:/root/tmp
environment: environment:
- CONNECT_TO_GRID=True - CONNECT_TO_GRID=true
- SELENIUM_HOST=selenium_hub - SELENIUM_HOST=selenium_hub
# Enable it for msite testing # Enable it for msite testing
#- BROWSER_NAME=chrome #- BROWSER_NAME=chrome
@ -60,14 +60,14 @@ services:
- 6080 - 6080
# Change path of apk that you want to test. I use sample_apk that I provide in folder "example" # Change path of apk that you want to test. I use sample_apk that I provide in folder "example"
volumes: volumes:
- $PWD/example/sample_apk:/root/tmp - $PWD/example/sample_apk:/root/tmp/sample_apk
- ./video-nexus_7.1.1:/tmp/video - ./video-nexus_7.1.1:/tmp/video
environment: environment:
- DEVICE=Nexus 5 - DEVICE=Nexus 5
- CONNECT_TO_GRID=True - CONNECT_TO_GRID=true
- APPIUM=true - APPIUM=true
- SELENIUM_HOST=selenium_hub - SELENIUM_HOST=selenium_hub
- AUTO_RECORD=True - AUTO_RECORD=true
# Docker-Android for mobile website testing with chrome browser # Docker-Android for mobile website testing with chrome browser
# Chrome browser exists only for version 7.0 and 7.1.1 # Chrome browser exists only for version 7.0 and 7.1.1
@ -85,11 +85,11 @@ services:
- ./video-samsung_7.1.1:/tmp/video - ./video-samsung_7.1.1:/tmp/video
environment: environment:
- DEVICE=Samsung Galaxy S6 - DEVICE=Samsung Galaxy S6
- CONNECT_TO_GRID=True - CONNECT_TO_GRID=true
- APPIUM=true - APPIUM=true
- SELENIUM_HOST=selenium_hub - SELENIUM_HOST=selenium_hub
- MOBILE_WEB_TEST=True - MOBILE_WEB_TEST=true
- AUTO_RECORD=True - AUTO_RECORD=true
# Docker-Android for mobile website testing with default browser # Docker-Android for mobile website testing with default browser
# Default browser exists only for version 5.0.1, 5.1.1 and 6.0 # Default browser exists only for version 5.0.1, 5.1.1 and 6.0
@ -107,8 +107,8 @@ services:
- ./video-samsung_5.1.1:/tmp/video - ./video-samsung_5.1.1:/tmp/video
environment: environment:
- DEVICE=Samsung Galaxy S6 - DEVICE=Samsung Galaxy S6
- CONNECT_TO_GRID=True - CONNECT_TO_GRID=true
- APPIUM=true - APPIUM=true
- SELENIUM_HOST=selenium_hub - SELENIUM_HOST=selenium_hub
- MOBILE_WEB_TEST=True - MOBILE_WEB_TEST=true
- AUTO_RECORD=True - AUTO_RECORD=true

View file

@ -1,4 +1,4 @@
FROM appium/appium:1.7.2-p1 FROM appium/appium:1.8.1-p2
LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>" LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>"
@ -83,19 +83,18 @@ ENV ANDROID_VERSION=$ANDROID_VERSION \
IMG_TYPE=$IMG_TYPE \ IMG_TYPE=$IMG_TYPE \
BROWSER=$BROWSER BROWSER=$BROWSER
ENV PATH ${PATH}:${ANDROID_HOME}/build-tools ENV PATH ${PATH}:${ANDROID_HOME}/build-tools
RUN echo y | sdkmanager "platforms;android-${API_LEVEL}" && \ RUN yes | sdkmanager --licenses && \
echo y | sdkmanager "system-images;android-${API_LEVEL};${IMG_TYPE};${SYS_IMG}" && \ sdkmanager "platforms;android-${API_LEVEL}" "system-images;android-${API_LEVEL};${IMG_TYPE};${SYS_IMG}" "emulator"
echo y | sdkmanager "emulator"
RUN rm ${ANDROID_HOME}/tools/emulator \ RUN rm ${ANDROID_HOME}/tools/emulator \
&& ln -s ${ANDROID_HOME}/emulator/emulator64-${PROCESSOR} ${ANDROID_HOME}/tools/emulator && ln -s ${ANDROID_HOME}/emulator/emulator64-${PROCESSOR} ${ANDROID_HOME}/tools/emulator
ENV LD_LIBRARY_PATH=$ANDROID_HOME/emulator/lib64:$ANDROID_HOME/emulator/lib64/qt/lib ENV LD_LIBRARY_PATH=$ANDROID_HOME/emulator/lib64:$ANDROID_HOME/emulator/lib64/qt/lib
#============================================== #==============================================
# Download chrome driver v2.26 # Download latest version of chromedriver
# to be able to use chrome browser in emulator # to be able to use Chrome browser in emulator
# Issue: https://github.com/butomo1989/docker-android/commit/6406504f944dae73d0a0c5d8e71a17a47dff9b33
#============================================== #==============================================
RUN wget -nv -O chrome.zip "https://chromedriver.storage.googleapis.com/2.26/chromedriver_linux64.zip" \ RUN LATEST_VERSION=$(curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE) \
&& wget -nv -O chrome.zip "https://chromedriver.storage.googleapis.com/$LATEST_VERSION/chromedriver_linux64.zip" \
&& unzip -x chrome.zip \ && unzip -x chrome.zip \
&& rm chrome.zip && rm chrome.zip

View file

@ -1,4 +1,4 @@
FROM appium/appium:1.7.2-p1 FROM appium/appium:1.8.1-p2
LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>" LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>"
@ -86,7 +86,7 @@ RUN wget -nv -O noVNC.zip "https://github.com/kanaka/noVNC/archive/${NOVNC_SHA}
ARG ANDROID_VERSION=5.0.1 ARG ANDROID_VERSION=5.0.1
ARG API_LEVEL=21 ARG API_LEVEL=21
ARG PROCESSOR=x86 ARG PROCESSOR=x86
ARG SYS_IMG=x86_64 ARG SYS_IMG=x86
ARG IMG_TYPE=google_apis ARG IMG_TYPE=google_apis
ARG BROWSER=android ARG BROWSER=android
ENV ANDROID_VERSION=$ANDROID_VERSION \ ENV ANDROID_VERSION=$ANDROID_VERSION \
@ -96,20 +96,15 @@ ENV ANDROID_VERSION=$ANDROID_VERSION \
IMG_TYPE=$IMG_TYPE \ IMG_TYPE=$IMG_TYPE \
BROWSER=$BROWSER BROWSER=$BROWSER
ENV PATH ${PATH}:${ANDROID_HOME}/build-tools ENV PATH ${PATH}:${ANDROID_HOME}/build-tools
RUN echo y | sdkmanager "platforms;android-${API_LEVEL}" && \ RUN yes | sdkmanager --licenses && \
echo y | sdkmanager "system-images;android-${API_LEVEL};${IMG_TYPE};${SYS_IMG}" && \ sdkmanager "platforms;android-${API_LEVEL}" "system-images;android-${API_LEVEL};${IMG_TYPE};${SYS_IMG}" "emulator"
echo y | sdkmanager "emulator"
RUN rm ${ANDROID_HOME}/tools/emulator \
&& ln -s ${ANDROID_HOME}/emulator/emulator64-${PROCESSOR} ${ANDROID_HOME}/tools/emulator
ENV LD_LIBRARY_PATH=$ANDROID_HOME/emulator/lib64:$ANDROID_HOME/emulator/lib64/qt/lib
#============================================== #==============================================
# Download chrome driver v2.26 # Download latest version of chromedriver
# to be able to use chrome browser in emulator # to be able to use Chrome browser in emulator
# Issue: https://github.com/butomo1989/docker-android/commit/6406504f944dae73d0a0c5d8e71a17a47dff9b33
#============================================== #==============================================
RUN wget -nv -O chrome.zip "https://chromedriver.storage.googleapis.com/2.26/chromedriver_linux64.zip" \ RUN LATEST_VERSION=$(curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE) \
&& wget -nv -O chrome.zip "https://chromedriver.storage.googleapis.com/$LATEST_VERSION/chromedriver_linux64.zip" \
&& unzip -x chrome.zip \ && unzip -x chrome.zip \
&& rm chrome.zip && rm chrome.zip

125
docker/Genymotion Normal file
View file

@ -0,0 +1,125 @@
FROM appium/appium:1.8.1-p2
LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>"
#=============
# Set WORKDIR
#=============
WORKDIR /root
#==================
# General Packages
#------------------
# xterm
# Terminal emulator
# supervisor
# Process manager
# socat
# Port forwarder
#------------------
# Genymotion spec
#------------------
# bzip2
# File compression
#------------------
# NoVNC Packages
#------------------
# x11vnc
# VNC server for X display
# openbox
# Windows manager
# menu
# Debian menu
# python-numpy
# Numpy, For faster performance: https://github.com/novnc/websockify/issues/77
# net-tools
# Netstat
#------------------
# Video Recording
#------------------
# ffmpeg
# Video recorder
# jq
# Sed for JSON data
#==================
RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
xterm \
supervisor \
socat \
bzip2 \
x11vnc \
openbox \
menu \
python-numpy \
net-tools \
ffmpeg \
jq \
&& rm -rf /var/lib/apt/lists/*
#=======
# noVNC
# Use same commit id that docker-selenium uses
# https://github.com/elgalu/docker-selenium/blob/236b861177bd2917d864e52291114b1f5e4540d7/Dockerfile#L412-L413
#=======
ENV NOVNC_SHA="b403cb92fb8de82d04f305b4f14fa978003890d7" \
WEBSOCKIFY_SHA="558a6439f14b0d85a31145541745e25c255d576b"
RUN wget -nv -O noVNC.zip "https://github.com/kanaka/noVNC/archive/${NOVNC_SHA}.zip" \
&& unzip -x noVNC.zip \
&& rm noVNC.zip \
&& mv noVNC-${NOVNC_SHA} noVNC \
&& wget -nv -O websockify.zip "https://github.com/kanaka/websockify/archive/${WEBSOCKIFY_SHA}.zip" \
&& unzip -x websockify.zip \
&& mv websockify-${WEBSOCKIFY_SHA} ./noVNC/utils/websockify \
&& rm websockify.zip \
&& ln noVNC/vnc_auto.html noVNC/index.html
#================================================
# noVNC Default Configurations
# These Configurations can be changed through -e
#================================================
ENV DISPLAY=:0 \
SCREEN=0 \
SCREEN_WIDTH=1600 \
SCREEN_HEIGHT=900 \
SCREEN_DEPTH=16 \
LOCAL_PORT=5900 \
TARGET_PORT=6080 \
TIMEOUT=1 \
VIDEO_PATH=/tmp/video \
LOG_PATH=/var/log/supervisor
#====================
# Install genymotion
#====================
ARG GENYMOTION_VERSION=2.12.1
ENV GENYMOTION=true \
GENYMOTION_VERSION=$GENYMOTION_VERSION \
PATH="${PATH}:/opt/genymobile/genymotion/" \
APPIUM_LOG=$LOG_PATH/appium.log
RUN wget -nv -O genymotion.bin "https://dl.genymotion.com/releases/genymotion-${GENYMOTION_VERSION}/genymotion-${GENYMOTION_VERSION}-linux_x64.bin" \
&& chmod +x ./genymotion.bin \
&& yes | ./genymotion.bin \
&& rm genymotion.bin
COPY genymotion/generate_config.sh genymotion/geny_start.sh /root/
#===============
# Expose Ports
#---------------
# 4723
# Appium port
# 6080
# noVNC port
# 5555
# ADB connection port
#===============
EXPOSE 4723 6080 5555
#=======================
# Run docker-genymotion
#=======================
COPY src /root/src
COPY supervisord.conf /root/
RUN chmod -R +x /root/src && chmod +x /root/supervisord.conf /root/geny_start.sh
RUN gmtool --cloud config use_custom_sdk=on sdk_path=/root
CMD ["./geny_start.sh"]

View file

@ -1,4 +1,4 @@
FROM appium/appium:1.7.2-p1 FROM appium/appium:1.8.1-p2
LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>" LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>"
@ -85,7 +85,8 @@ ENV DISPLAY=:0 \
#========================= #=========================
# Set default variables # Set default variables
#========================= #=========================
ENV REAL_DEVICE=True ENV APPIUM_LOG=$LOG_PATH/appium.log
ENV REAL_DEVICE=true
ENV BROWSER=android ENV BROWSER=android
#=============== #===============

29
genymotion/example/geny.yml Executable file
View file

@ -0,0 +1,29 @@
# Note: It requires docker-compose 1.13.0
#
# Usage: docker-compose up -d
version: "2.2"
services:
# Selenium hub
selenium_hub:
image: selenium/hub:3.12.0-americium
ports:
- 4444:4444
# Please stop this container by using docker stop instead of docker-compose stop
genymotion:
image: butomo1989/docker-android-genymotion
depends_on:
- selenium_hub
ports:
- 6080:6080
- 4723:4723
volumes:
- $PWD/sample_apk:/root/tmp/sample_apk
- $PWD/sample_devices:/root/tmp
environment:
- GENY_TEMPLATE=/root/tmp/devices.json
- USER=xxx
- PASS=xxx
- LICENSE=xxx
- CONNECT_TO_GRID=true

Binary file not shown.

View file

@ -0,0 +1,11 @@
[
{
"template": "Samsung Galaxy S7 - 6.0.0 - API 23 - 1440x2560",
"device": "SamsungS7V6",
"port": 38727
},
{
"template": "Google Nexus 6 - 8.0 - API 26 - 1440x2560",
"device": "Nexus6V8"
}
]

81
genymotion/generate_config.sh Executable file
View file

@ -0,0 +1,81 @@
#!/bin/bash
node_config_json=$1
if [ -z "$PLATFORM_NAME" ]; then
PLATFORM_NAME="Android"
fi
if [ -z "$APPIUM_HOST" ]; then
APPIUM_HOST=$(hostname -i)
fi
if [ -z "$APPIUM_PORT" ]; then
APPIUM_PORT=4723
fi
if [ -z "$SELENIUM_HOST" ]; then
SELENIUM_HOST="172.17.0.1"
fi
if [ -z "$SELENIUM_PORT" ]; then
SELENIUM_PORT=4444
fi
if [ -z "$BROWSER_NAME" ]; then
BROWSER_NAME="android"
fi
if [ -z "$NODE_TIMEOUT" ]; then
NODE_TIMEOUT=300
fi
#Get device names
devices=($(adb devices | grep -oP "\K([^ ]+)(?=\sdevice(\W|$))"))
echo "Devices found: ${#devices[@]}"
#Create capabilities json configs
function create_capabilities() {
capabilities=""
for name in ${devices[@]}; do
os_version="$(adb -s $name shell getprop ro.build.version.release | tr -d '\r')"
capabilities+=$(cat <<_EOF
{
"platform": "$PLATFORM_NAME",
"platformName": "$PLATFORM_NAME",
"version": "$os_version",
"browserName": "$BROWSER_NAME",
"deviceName": "$name",
"maxInstances": 1,
"applicationName": "$name"
}
_EOF
)
if [ ${devices[-1]} != $name ]; then
capabilities+=', '
fi
done
echo "$capabilities"
}
#Final node configuration json string
nodeconfig=$(cat <<_EOF
{
"capabilities": [$(create_capabilities)],
"configuration": {
"cleanUpCycle": 2000,
"timeout": $NODE_TIMEOUT,
"proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy",
"url": "http://$APPIUM_HOST:$APPIUM_PORT/wd/hub",
"host": "$APPIUM_HOST",
"port": $APPIUM_PORT,
"maxSession": 6,
"register": true,
"registerCycle": 5000,
"hubHost": "$SELENIUM_HOST",
"hubPort": $SELENIUM_PORT
}
}
_EOF
)
echo "$nodeconfig" > $node_config_json

29
genymotion/geny_start.sh Executable file
View file

@ -0,0 +1,29 @@
#!/bin/bash
# This script is needed because of https://www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/
if [ -z "$GENY_TEMPLATE" ]; then
GENY_TEMPLATE="/root/tmp/devices.json"
fi
if [ ! -f "$GENY_TEMPLATE" ]; then
echo "File not found! Nothing to do!"
exit 1
fi
getAbort() {
if [ "$GENYMOTION" = true ]; then
contents=$(cat $GENY_TEMPLATE)
echo "ABORT SIGNAL detected! Stopping all created emulators..."
for row in $(echo "${contents}" | jq -r '.[] | @base64'); do
get_value() {
echo ${row} | base64 --decode | jq -r ${1}
}
gmtool --cloud admin stopdisposable $(get_value '.device')
done
echo "Done"
fi
}
trap 'getAbort; exit' EXIT
/usr/bin/supervisord --configuration supervisord.conf

BIN
images/Genymotion_cloud.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

BIN
images/appiumconf2018.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

BIN
images/logo_genymotion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

29
revert.sh Normal file
View file

@ -0,0 +1,29 @@
#!/bin/bash
IMAGE_NAME="butomo1989/docker-android"
if [ -z "$1" ]; then
read -p "Type : " TYPE
else
TYPE=$1
fi
if [ -z "$2" ]; then
read -p "Version : " VERSION
else
VERSION=$2
fi
declare -a versions=("7.1.1" "7.0" "6.0" "5.1.1" "5.0.1")
## now loop through the above array
for v in "${versions[@]}"
do
IMAGE="$IMAGE_NAME-$TYPE-$v"
IMAGE_OLD="$IMAGE:$VERSION"
IMAGE_LATEST="$IMAGE:latest"
echo "Revert image \"$IMAGE_LATEST\" to version \"$IMAGE_OLD\""
docker pull $IMAGE_OLD
docker tag $IMAGE_OLD $IMAGE_LATEST
docker push $IMAGE_LATEST
done

View file

@ -105,7 +105,13 @@ def appium_run(avd_name: str):
:param avd_name: Name of android virtual device / emulator :param avd_name: Name of android virtual device / emulator
""" """
cmd = 'appium' DEFAULT_LOG_PATH = '/var/log/supervisor/appium.log'
cmd = 'appium --log {log}'.format(log=os.getenv('APPIUM_LOG', DEFAULT_LOG_PATH))
relaxed_security = convert_str_to_bool(str(os.getenv('RELAXED_SECURITY', False)))
logger.info('Relaxed security? {rs}'.format(rs=relaxed_security))
if relaxed_security:
cmd += ' --relaxed-security'
default_web_browser = os.getenv('BROWSER') default_web_browser = os.getenv('BROWSER')
if default_web_browser == 'chrome': if default_web_browser == 'chrome':
@ -184,13 +190,17 @@ def run():
prepare_avd(device, avd_name) prepare_avd(device, avd_name)
logger.info('Run emulator...') logger.info('Run emulator...')
cmd = 'emulator -avd {name} -gpu off'.format(name=avd_name) dp_size = os.getenv('DATAPARTITION', '550m')
subprocess.Popen(cmd.split()) with open("/root/android_emulator/config.ini", "a") as cfg:
cfg.write('\ndisk.dataPartition.size={dp}'.format(dp=dp_size))
cmd = 'emulator/emulator @{name} -gpu off -verbose'.format(name=avd_name)
appium = convert_str_to_bool(str(os.getenv('APPIUM', False))) appium = convert_str_to_bool(str(os.getenv('APPIUM', False)))
if appium: if appium:
subprocess.Popen(cmd.split())
logger.info('Run appium server...') logger.info('Run appium server...')
appium_run(avd_name) appium_run(avd_name)
else:
result = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE).communicate()
if __name__ == '__main__': if __name__ == '__main__':
run() run()

View file

@ -1,13 +1,62 @@
#!/bin/bash #!/bin/bash
if [ -z $REAL_DEVICE ]; then if [ -z "$GENY_TEMPLATE" ]; then
python3 -m src.app GENY_TEMPLATE="/root/tmp/devices.json"
fi
function prepare_geny_cloud() {
contents=$(cat $GENY_TEMPLATE)
# Register
gmtool config username="${USER}" password="${PASS}"
gmtool license register "${LICENSE}"
# Start device(s)
echo "Creating device(s) based on given json file..."
for row in $(echo "${contents}" | jq -r '.[] | @base64'); do
get_value() {
echo ${row} | base64 --decode | jq -r ${1}
}
template=$(get_value '.template')
device=$(get_value '.device')
port=$(get_value '.port')
if [[ $port != null ]]; then
echo "Starting \"$device\" with template name \"$template\" on port \"$port\"..."
gmtool --cloud admin startdisposable "${template}" "${device}" --adb-serial-port "${port}"
else else
CMD="appium" echo "Starting \"$device\" with template name \"$template\"..."
if [ ! -z "$CONNECT_TO_GRID" ]; then gmtool --cloud admin startdisposable "${template}" "${device}"
fi
done
}
function run_appium() {
echo "Preparing appium-server..."
CMD="appium --log $APPIUM_LOG"
if [ "$CONNECT_TO_GRID" = true ]; then
NODE_CONFIG_JSON="/root/src/nodeconfig.json" NODE_CONFIG_JSON="/root/src/nodeconfig.json"
/root/generate_config.sh $NODE_CONFIG_JSON /root/generate_config.sh $NODE_CONFIG_JSON
CMD+=" --nodeconfig $NODE_CONFIG_JSON" CMD+=" --nodeconfig $NODE_CONFIG_JSON"
fi fi
$CMD
if [ "$RELAXED_SECURITY" = true ]; then
CMD+=" --relaxed-security"
fi
echo "Preparation is done"
$CMD
}
if [ "$REAL_DEVICE" = true ]; then
echo "Using real device"
run_appium
elif [ "$GENYMOTION" = true ]; then
echo "Using Genymotion"
prepare_geny_cloud
run_appium
else
echo "Using Emulator"
python3 -m src.app
fi fi

View file

@ -16,12 +16,12 @@ function auto_record() {
echo "Auto record: $AUTO_RECORD" echo "Auto record: $AUTO_RECORD"
sleep 6 sleep 6
while [ $AUTO_RECORD == "True" ]; do while [ "$AUTO_RECORD" = true ]; do
# Check if there is test running # Check if there is test running
no_test=true no_test=true
while $no_test; do while $no_test; do
task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value') task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value')
if [ "$task" == "" ] || [ "$task" == "[]" ]; then if [ "$task" = "" ] || [ "$task" = "[]" ]; then
sleep .5 sleep .5
else else
start & start &
@ -30,9 +30,9 @@ function auto_record() {
done done
# Check if test is finished # Check if test is finished
while [ $no_test == false ]; do while [ $no_test = false ]; do
task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value') task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value')
if [ "$task" == "" ] || [ "$task" == "[]" ]; then if [ "$task" = "" ] || [ "$task" = "[]" ]; then
stop stop
no_test=true no_test=true
else else

View file

@ -53,21 +53,25 @@ class TestApp(TestCase):
self.assertEqual(app.convert_str_to_bool(True), None) self.assertEqual(app.convert_str_to_bool(True), None)
@mock.patch('src.app.prepare_avd') @mock.patch('src.app.prepare_avd')
@mock.patch('builtins.open')
@mock.patch('subprocess.Popen') @mock.patch('subprocess.Popen')
def test_run_with_appium(self, mocked_avd, mocked_subprocess): def test_run_with_appium(self, mocked_avd, mocked_open, mocked_subprocess):
with mock.patch('src.app.appium_run') as mocked_appium: with mock.patch('src.app.appium_run') as mocked_appium:
os.environ['APPIUM'] = str(True) os.environ['APPIUM'] = str(True)
app.run() app.run()
self.assertTrue(mocked_avd.called) self.assertTrue(mocked_avd.called)
self.assertTrue(mocked_open.called)
self.assertTrue(mocked_subprocess.called) self.assertTrue(mocked_subprocess.called)
self.assertTrue(mocked_appium.called) self.assertTrue(mocked_appium.called)
@mock.patch('src.app.prepare_avd') @mock.patch('src.app.prepare_avd')
@mock.patch('builtins.open')
@mock.patch('subprocess.Popen') @mock.patch('subprocess.Popen')
def test_run_withhout_appium(self, mocked_avd, mocked_subprocess): def test_run_withhout_appium(self, mocked_avd, mocked_open, mocked_subprocess):
with mock.patch('src.app.appium_run') as mocked_appium: with mock.patch('src.app.appium_run') as mocked_appium:
os.environ['APPIUM'] = str(False) os.environ['APPIUM'] = str(False)
app.run() app.run()
self.assertTrue(mocked_avd.called) self.assertTrue(mocked_avd.called)
self.assertTrue(mocked_open.called)
self.assertTrue(mocked_subprocess.called) self.assertTrue(mocked_subprocess.called)
self.assertFalse(mocked_appium.called) self.assertFalse(mocked_appium.called)