Compare commits

...
39 Commits
Author SHA1 Message Date
butomo1989 5c9ad32522 Automated some steps in screen mirroring for real device 2018-02-12 18:09:14 +01:00
butomo1989 366aa8b3b3 Added real device configuration in docker-compose 2018-02-12 11:07:37 +01:00
butomo1989 905f2c723b Using the latest base image 2018-02-12 10:49:26 +01:00
Budi UtomoandGitHub 0e028d9a4a Updated version of docker-selenium hub 2018-02-06 20:33:24 +01:00
butomo1989 ce61b992f9 Using the newest version of base image 2018-01-29 16:57:46 +01:00
butomo1989 e62573036c Added dockerandroid logo 2017-11-23 21:03:12 +01:00
butomo1989 e27b2e5fdf Edited permission 2017-11-21 15:39:08 +01:00
butomo1989 fdd4a86c40 Merge remote-tracking branch 'origin/master' into release-0.9 2017-11-14 15:40:21 +01:00
Budi UtomoandGitHub 15012fd3b4 Edited README.md 2017-11-14 15:38:46 +01:00
butomo1989 1f440e1a07 Using the latest image 2017-11-09 11:44:35 +01:00
butomo1989 567a494ccb Using new usage process of new SDK 2017-11-09 11:25:21 +01:00
butomo1989 d28c4dc5e0 Fixed docker images 2017-11-07 17:33:22 +01:00
butomo1989 7a052b7e2f Merge remote-tracking branch 'origin' into update-sdk 2017-11-03 12:26:05 +01:00
butomo1989 988397318f Updated README.md 2017-11-03 11:15:38 +01:00
butomo1989 0d6356ba47 Upgraded README.md 2017-11-01 15:53:25 +01:00
butomo1989 0ea71ea6b8 Refactored auto-recording function 2017-10-30 20:42:36 +01:00
butomo1989 08ff64d950 Fixed docker-compose volume 2017-10-30 20:41:27 +01:00
butomo1989 fcffca21ff Fixed error due to file name 2017-10-27 21:02:00 +02:00
butomo1989 95adfd1fbd Installed jq 2017-10-27 21:00:10 +02:00
butomo1989 5029d33528 Fixed error 2017-10-27 20:59:19 +02:00
Budi UtomoandGitHub c9ab42ecfb Merge pull request #28 from thelittlefireman/master
fix file error when start/stop/start container
2017-08-01 16:16:12 +02:00
thelittlefiremanandGitHub 7c48af9b84 fix codacy-bot warrning 2017-08-01 10:30:04 +02:00
thelittlefiremanandGitHub e1d6e3cdbe delete useless code 2017-07-31 15:58:38 +02:00
thelittlefiremanandGitHub 648010d519 delete useless code 2017-07-31 15:56:50 +02:00
thelittlefiremanandGitHub 9d3cb60f41 add unit test last case 2017-07-31 15:28:33 +02:00
thelittlefiremanandGitHub e2ad6b75d2 add unit test to symlink_force 2017-07-31 15:12:46 +02:00
thelittlefiremanandGitHub 486fb5825b fix bad python impl 2017-07-29 22:51:36 +02:00
thelittlefiremanandGitHub e56eb0e3ab fix : file already exist on start and stop container 2017-07-28 22:45:34 +02:00
thelittlefiremanandGitHub 6fe6a80f40 Merge pull request #1 from thelittlefireman/thelittlefireman-fix-files-already-exist
fix python error when files already exist
2017-07-28 15:15:08 +02:00
thelittlefiremanandGitHub f7b30c3129 fix python error when files already exist
related to :
```
  File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main                                                                                                                                 
    "__main__", mod_spec)                                                                                                                                                                              
  File "/usr/lib/python3.5/runpy.py", line 85, in _run_code                                                                                                                                            
    exec(code, run_globals)                                                                                                                                                                            
  File "/root/src/app.py", line 189, in <module>                                                                                                                                                       
    run()                                                                                                                                                                                              
  File "/root/src/app.py", line 178, in run                                                                                                                                                            
    prepare_avd(device, avd_name)                                                                                                                                                                      
  File "/root/src/app.py", line 74, in prepare_avd                                                                                                                                                     
    os.symlink(os.path.join(skin_rsc_path, s), os.path.join(skin_dst_path, s))                                                                                                                         
FileExistsError: [Errno 17] File exists: '/root/devices/skins/galaxy_nexus' -> '/root/platforms/android-25/skins/galaxy_nexus'                                                                         
Traceback (most recent call last):                                                                                                                                                                     
  File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main                                                                                                                                 
    "__main__", mod_spec)                                                                                                                                                                              
  File "/usr/lib/python3.5/runpy.py", line 85, in _run_code                                                                                                                                            
    exec(code, run_globals)                                                                                                                                                                            
  File "/root/src/app.py", line 189, in <module>                                                                                                                                                       
    run()                                                                                                                                                                                              
  File "/root/src/app.py", line 178, in run                                                                                                                                                            
    prepare_avd(device, avd_name)                                                                                                                                                                      
  File "/root/src/app.py", line 74, in prepare_avd                                                                                                                                                     
    os.symlink(os.path.join(skin_rsc_path, s), os.path.join(skin_dst_path, s))                                                                                                                         
FileExistsError: [Errno 17] File exists: '/root/devices/skins/galaxy_nexus' -> '/root/platforms/android-25/skins/galaxy_nexus' 
```
2017-07-28 15:13:45 +02:00
butomo1989 1062da3dcc Fixed installation issue 2017-07-18 17:44:09 +02:00
butomo1989 c431118465 Using the latest image version of appium-docker-android 2017-07-18 12:06:38 +02:00
butomo1989 b6a1a57bed Enable video recording 2017-07-14 20:40:14 +02:00
butomo1989 83baa09384 Fixed not expected error in supervisor 2017-07-13 18:55:32 +02:00
Budi UtomoandGitHub 8a69c64de3 Merge pull request #22 from andrcuns/real_device_mirroring
Real device mirroring
2017-07-08 23:57:52 +02:00
Andrejs Cunskis 488e53149c Release script for image with real device support 2017-07-07 23:46:04 +03:00
Andrejs Cunskis 2bc30edf4c Add support for real device and screen mirroring 2017-07-03 22:50:37 +03:00
butomo1989 8d544448f1 All badges in one line 2017-06-29 09:05:56 +02:00
The Gitter BadgerandBudi Utomo f7b560a28b Add Gitter badge (#19) 2017-06-29 09:04:05 +02:00
25 changed files with 433 additions and 78 deletions
+4 -1
View File
@@ -6,4 +6,7 @@
.coverage .coverage
coverage.xml coverage.xml
xunit.xml xunit.xml
coverage/* coverage/*
# Video
video*
+6 -6
View File
@@ -11,12 +11,12 @@ services:
install: "pip install -r requirements.txt" install: "pip install -r requirements.txt"
env: env:
matrix: - ANDROID_VERSION=5.0.1
- ANDROID_VERSION=5.0.1 - ANDROID_VERSION=5.1.1
- ANDROID_VERSION=5.1.1 - ANDROID_VERSION=6.0
- ANDROID_VERSION=6.0 - ANDROID_VERSION=7.0
- ANDROID_VERSION=7.0 - ANDROID_VERSION=7.1.1
- ANDROID_VERSION=7.1.1 - REAL_DEVICE=True
script: bash travis.sh script: bash travis.sh
+25 -10
View File
@@ -1,15 +1,18 @@
Docker-Android <p align="center">
============== <img id="header" src="./images/logo_dockerandroid_small.png" />
</p>
[![Join the chat at https://gitter.im/butomo1989/docker-android](https://badges.gitter.im/butomo1989/docker-android.svg)](https://gitter.im/butomo1989/docker-android?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/butomo1989/docker-android.svg?branch=master)](https://travis-ci.org/butomo1989/docker-android) [![Build Status](https://travis-ci.org/butomo1989/docker-android.svg?branch=master)](https://travis-ci.org/butomo1989/docker-android)
[![Docker Pulls](https://img.shields.io/docker/pulls/butomo1989/docker-android-x86-7.1.1.svg?style=flat-square&style=plastic)](https://hub.docker.com/r/butomo1989/docker-android-x86-7.1.1/)
[![codecov](https://codecov.io/gh/butomo1989/docker-android/branch/master/graph/badge.svg)](https://codecov.io/gh/butomo1989/docker-android) [![codecov](https://codecov.io/gh/butomo1989/docker-android/branch/master/graph/badge.svg)](https://codecov.io/gh/butomo1989/docker-android)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3f000ffb97db45a59161814e1434c429)](https://www.codacy.com/app/butomo1989/docker-appium?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=butomo1989/docker-appium&amp;utm_campaign=Badge_Grade) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/3f000ffb97db45a59161814e1434c429)](https://www.codacy.com/app/butomo1989/docker-appium?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=butomo1989/docker-appium&amp;utm_campaign=Badge_Grade)
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.
Samsung Device | Google Device Emulator - Samsung Device | Emulator - Nexus Device | Real Device
:---------------------------:|:---------------------------: :---------------------------:|:---------------------------:|:---------------------------:
![][docker android samsung] | ![][docker android nexus] ![][emulator samsung] |![][emulator nexus] |![][real device]
Purpose Purpose
------- -------
@@ -27,7 +30,9 @@ Advantages compare with other docker-android projects
2. Emulator for different devices / skins, such as Samsung Galaxy S6, LG Nexus 4, HTC Nexus One and more. 2. Emulator for different devices / skins, such as Samsung Galaxy S6, LG Nexus 4, HTC Nexus One and more.
3. Ability to connect to Selenium Grid 3. Ability to connect to Selenium Grid
4. Ability to control emulator from outside container by using adb connect 4. Ability to control emulator from outside container by using adb connect
5. Open source with more features coming (monkey test, support real devices with screen mirroring and video recording) 5. Support real devices with screen mirroring
6. Ability to record video during test execution for debugging
7. Open source with more features coming
List of Docker images List of Docker images
--------------------- ---------------------
@@ -44,6 +49,7 @@ List of Docker images
|OSX / Windows|6.0|23|butomo1989/docker-android-arm-6.0|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-arm-6.0.svg)](https://microbadger.com/images/butomo1989/docker-android-arm-6.0 "Get your own image badge on microbadger.com")| |OSX / Windows|6.0|23|butomo1989/docker-android-arm-6.0|[![](https://images.microbadger.com/badges/image/butomo1989/docker-android-arm-6.0.svg)](https://microbadger.com/images/butomo1989/docker-android-arm-6.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.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")|
List of Devices List of Devices
--------------- ---------------
@@ -126,10 +132,13 @@ If you want to use appium to test UI of your android application, you need to sh
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
You can deactivate auto_record by changing the value to "False" in docker-compose file. e.g. change value to "False" in this [line].
### Docker-Compose ### Docker-Compose
![][compose] ![][compose]
![][connected_devices]
There is [example of compose file] to run complete selenium grid and docker-android container as nodes. [docker-compose] version [1.13.0] or higher is required to be able to execute that compose file. There is [example of compose file] to run complete selenium grid and docker-android container as nodes. [docker-compose] version [1.13.0] or higher is required to be able to execute that compose file.
@@ -194,15 +203,21 @@ All logs inside container are stored under folder **/var/log/supervisor**. you c
docker exec -it android-container tail -f /var/log/supervisor/docker-android.stdout.log docker exec -it android-container tail -f /var/log/supervisor/docker-android.stdout.log
``` ```
Special Thanks
--------------
- [Gian Christanto] for creating a great logo!
[appium]: <https://appium.io> [appium]: <https://appium.io>
[espresso]: <https://google.github.io/android-testing-support-library/docs/espresso/> [espresso]: <https://google.github.io/android-testing-support-library/docs/espresso/>
[robotium]: <https://github.com/RobotiumTech/robotium> [robotium]: <https://github.com/RobotiumTech/robotium>
[docker android samsung]: <images/docker_android_samsung.png> [emulator samsung]: <images/emulator_samsung_galaxy_s6.png>
[docker android nexus]: <images/docker_android_nexus.png> [emulator nexus]: <images/emulator_nexus_5.png>
[real device]: <images/real_device.png>
[compose]: <images/compose.png> [compose]: <images/compose.png>
[connected_devices]: <images/connected_devices.png> [line]: <https://github.com/butomo1989/docker-android/blob/master/docker-compose.yml#L30>
[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>
[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/>
Regular → Executable
+41 -5
View File
@@ -6,26 +6,50 @@ version: "2.2"
services: services:
# Selenium hub # Selenium hub
selenium_hub: selenium_hub:
image: selenium/hub:3.4.0 image: selenium/hub:3.7.1
ports: ports:
- "4444:4444" - "4444:4444"
# Real devices
real_device:
image: butomo1989/docker-android-real-device
privileged: true
depends_on:
- selenium_hub
ports:
- 6080:6080
volumes:
- ./video-real-device:/tmp/video
- /dev/bus/usb:/dev/bus/usb
- ~/.android:/root/.android
environment:
- CONNECT_TO_GRID=True
- APPIUM=true
- SELENIUM_HOST=selenium_hub
- AUTO_RECORD=True
- BROWSER_NAME=chrome
# Docker-Android for Android application testing # Docker-Android for Android application testing
nexus_7.1.1: nexus_7.1.1:
image: butomo1989/docker-android-x86-7.1.1 image: butomo1989/docker-android-x86-7.1.1
privileged: true privileged: true
# Increase scale number if needed
scale: 1
depends_on:
- selenium_hub
- real_device
ports:
- 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
# Increase scale number if needed - ./video-nexus_7.1.1:/tmp/video
scale: 1
ports:
- 6080
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
# 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
@@ -34,14 +58,20 @@ services:
privileged: true privileged: true
# Increase scale number if needed # Increase scale number if needed
scale: 1 scale: 1
depends_on:
- selenium_hub
- real_device
ports: ports:
- 6080 - 6080
volumes:
- ./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
# 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
@@ -50,11 +80,17 @@ services:
privileged: true privileged: true
# Increase scale number if needed # Increase scale number if needed
scale: 1 scale: 1
depends_on:
- selenium_hub
- real_device
ports: ports:
- 6080 - 6080
volumes:
- ./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
+16 -4
View File
@@ -1,4 +1,4 @@
FROM appium/appium:1.6.6-beta-p0 FROM appium/appium:1.7.2-p1
LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>" LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>"
@@ -29,6 +29,13 @@ WORKDIR /root
# Numpy, For faster performance: https://github.com/novnc/websockify/issues/77 # Numpy, For faster performance: https://github.com/novnc/websockify/issues/77
# net-tools # net-tools
# Netstat # Netstat
#------------------
# Video Recording
#------------------
# ffmpeg
# Video recorder
# jq
# Sed for JSON data
#================== #==================
RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
xterm \ xterm \
@@ -39,6 +46,8 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
menu \ menu \
python-numpy \ python-numpy \
net-tools \ net-tools \
ffmpeg \
jq \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
#======= #=======
@@ -74,10 +83,12 @@ 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}" && \
echo y | sdkmanager "system-images;android-${API_LEVEL};${IMG_TYPE};${SYS_IMG}" && \
echo y | sdkmanager "emulator"
RUN rm ${ANDROID_HOME}/tools/emulator \ RUN rm ${ANDROID_HOME}/tools/emulator \
&& ln -s ${ANDROID_HOME}/tools/emulator64-${PROCESSOR} ${ANDROID_HOME}/tools/emulator && ln -s ${ANDROID_HOME}/emulator/emulator64-${PROCESSOR} ${ANDROID_HOME}/tools/emulator
RUN echo y | android update sdk --no-ui -a -t android-${API_LEVEL},sys-img-${SYS_IMG}-${IMG_TYPE}-${API_LEVEL} ENV LD_LIBRARY_PATH=$ANDROID_HOME/emulator/lib64:$ANDROID_HOME/emulator/lib64/qt/lib
#============================================== #==============================================
# Download chrome driver v2.26 # Download chrome driver v2.26
@@ -100,6 +111,7 @@ ENV DISPLAY=:0 \
LOCAL_PORT=5900 \ LOCAL_PORT=5900 \
TARGET_PORT=6080 \ TARGET_PORT=6080 \
TIMEOUT=1 \ TIMEOUT=1 \
VIDEO_PATH=/tmp/video \
LOG_PATH=/var/log/supervisor LOG_PATH=/var/log/supervisor
#=============== #===============
+17 -4
View File
@@ -1,4 +1,4 @@
FROM appium/appium:1.6.6-beta-p0 FROM appium/appium:1.7.2-p1
LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>" LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>"
@@ -30,6 +30,13 @@ WORKDIR /root
# net-tools # net-tools
# Netstat # Netstat
#------------------ #------------------
# Video Recording
#------------------
# ffmpeg
# Video recorder
# jq
# Sed for JSON data
#------------------
# KVM Package # KVM Package
# for emulator x86 # for emulator x86
# https://help.ubuntu.com/community/KVM/Installation # https://help.ubuntu.com/community/KVM/Installation
@@ -48,6 +55,8 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
menu \ menu \
python-numpy \ python-numpy \
net-tools \ net-tools \
ffmpeg \
jq \
qemu-kvm \ qemu-kvm \
libvirt-bin \ libvirt-bin \
ubuntu-vm-builder \ ubuntu-vm-builder \
@@ -87,10 +96,13 @@ 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}" && \
echo y | sdkmanager "system-images;android-${API_LEVEL};${IMG_TYPE};${SYS_IMG}" && \
echo y | sdkmanager "emulator"
RUN rm ${ANDROID_HOME}/tools/emulator \ RUN rm ${ANDROID_HOME}/tools/emulator \
&& ln -s ${ANDROID_HOME}/tools/emulator64-${PROCESSOR} ${ANDROID_HOME}/tools/emulator && ln -s ${ANDROID_HOME}/emulator/emulator64-${PROCESSOR} ${ANDROID_HOME}/tools/emulator
RUN echo y | android update sdk --no-ui -a -t android-${API_LEVEL},sys-img-${SYS_IMG}-${IMG_TYPE}-${API_LEVEL} ENV LD_LIBRARY_PATH=$ANDROID_HOME/emulator/lib64:$ANDROID_HOME/emulator/lib64/qt/lib
#============================================== #==============================================
# Download chrome driver v2.26 # Download chrome driver v2.26
@@ -113,6 +125,7 @@ ENV DISPLAY=:0 \
LOCAL_PORT=5900 \ LOCAL_PORT=5900 \
TARGET_PORT=6080 \ TARGET_PORT=6080 \
TIMEOUT=1 \ TIMEOUT=1 \
VIDEO_PATH=/tmp/video \
LOG_PATH=/var/log/supervisor LOG_PATH=/var/log/supervisor
#=============== #===============
+111 -1
View File
@@ -1 +1,111 @@
# TODO FROM appium/appium:1.7.2-p1
LABEL maintainer "Budi Utomo <budi.ut.1989@gmail.com>"
#=============
# Set WORKDIR
#=============
WORKDIR /root
#==================
# General Packages
#------------------
# xterm
# Terminal emulator
# supervisor
# Process manager
# socat
# Port forwarder
#------------------
# 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 \
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
#=========================
# Set default variables
#=========================
ENV REAL_DEVICE=True
ENV BROWSER=android
#===============
# Expose Ports
#---------------
# 4723
# Appium port
# 6080
# noVNC port
# 5555
# ADB connection port
#===============
EXPOSE 4723 6080 5555
#===================
# Run docker-appium
#===================
COPY sm/asm.jar /root/
COPY src /root/src
COPY supervisord.conf /root/
RUN chmod -R +x /root/src && chmod +x /root/supervisord.conf
CMD /usr/bin/supervisord --configuration supervisord.conf
Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

+1 -1
View File
@@ -163,7 +163,7 @@ function build() {
for v in "${versions[@]}"; do for v in "${versions[@]}"; do
# Find image type and default web browser # Find image type and default web browser
if [ "$v" == "5.0.1" ] || [ "$v" == "5.1.1" ]; then if [ "$v" == "5.0.1" ] || [ "$v" == "5.1.1" ]; then
IMG_TYPE=android IMG_TYPE=default
BROWSER=browser BROWSER=browser
elif [ "$v" == "6.0" ]; then elif [ "$v" == "6.0" ]; then
# It is because there is no ARM EABI v7a System Image for 6.0 # It is because there is no ARM EABI v7a System Image for 6.0
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
if [ -z "$1" ]; then
read -p "Task (build|push|all) : " TASK
else
TASK=$1
fi
if [ -z "$2" ]; then
read -p "Release version: " RELEASE
else
RELEASE=$2
fi
IMAGE="butomo1989/docker-android"
FILE_NAME=docker/Real_device
image_version="$IMAGE-real-device:$RELEASE"
image_latest="$IMAGE-real-device:latest"
function build() {
echo "[BUILD] Image name: $image_version and $image_latest"
echo "[BUILD] Dockerfile: $FILE_NAME"
docker build -t $image_version -f $FILE_NAME .
docker tag $image_version $image_latest
}
function push() {
echo "[PUSH] Image name: $image_version and $image_latest"
docker push $image_version
docker push $image_latest
}
case $TASK in
build)
build
;;
push)
push
;;
all)
build
push
;;
*)
echo "Invalid environment! Valid options: test, build, push, all"
;;
esac
Executable
BIN
View File
Binary file not shown.
+27 -20
View File
@@ -5,13 +5,23 @@ import logging
import os import os
import subprocess import subprocess
from src import CONFIG_FILE, ROOT, CHROME_DRIVER from src import CHROME_DRIVER, CONFIG_FILE, ROOT
from src import log from src import log
log.init() log.init()
logger = logging.getLogger('app') logger = logging.getLogger('app')
def symlink_force(target, link_name):
try:
os.symlink(target, link_name)
except OSError as e:
import errno
if e.errno == errno.EEXIST:
os.remove(link_name)
os.symlink(target, link_name)
def get_or_raise(env: str) -> str: def get_or_raise(env: str) -> str:
""" """
Check if needed environment variables are given. Check if needed environment variables are given.
@@ -61,22 +71,9 @@ def prepare_avd(device: str, avd_name: str):
:param device: Device name :param device: Device name
:param avd_name: Name of android virtual device / emulator :param avd_name: Name of android virtual device / emulator
""" """
cmd = 'echo no | android create avd -f -n {name} -t android-{api} -b {img_type}{sys_img}'.format(
name=avd_name, api=API_LEVEL, img_type='google_apis/' if IMG_TYPE == 'google_apis' else '',
sys_img=SYS_IMG)
# Link emulator skins
skin_rsc_path = os.path.join(ROOT, 'devices', 'skins')
logger.info('Skin ressource path: {rsc}'.format(rsc=skin_rsc_path))
skin_dst_path = os.path.join(ANDROID_HOME, 'platforms', 'android-{api}'.format(api=API_LEVEL), 'skins')
logger.info('Skin destination path: {dst}'.format(dst=skin_dst_path))
for s in os.listdir(skin_rsc_path):
os.symlink(os.path.join(skin_rsc_path, s), os.path.join(skin_dst_path, s))
# Hardware and its skin
device_name_bash = device.replace(' ', '\ ') device_name_bash = device.replace(' ', '\ ')
skin_name = device.replace(' ', '_').lower() skin_name = device.replace(' ', '_').lower()
logger.info('Device name in bash: {db}, Skin name: {skin}'.format(db=device_name_bash, skin=skin_name))
# For custom hardware profile # For custom hardware profile
profile_dst_path = os.path.join(ROOT, '.android', 'devices.xml') profile_dst_path = os.path.join(ROOT, '.android', 'devices.xml')
@@ -85,12 +82,21 @@ def prepare_avd(device: str, avd_name: str):
profile_src_path = os.path.join(ROOT, 'devices', 'profiles', '{profile}.xml'.format(profile=skin_name)) profile_src_path = os.path.join(ROOT, 'devices', 'profiles', '{profile}.xml'.format(profile=skin_name))
logger.info('Hardware profile resource path: {rsc}'.format(rsc=profile_src_path)) logger.info('Hardware profile resource path: {rsc}'.format(rsc=profile_src_path))
logger.info('Hardware profile destination path: {dst}'.format(dst=profile_dst_path)) logger.info('Hardware profile destination path: {dst}'.format(dst=profile_dst_path))
os.symlink(profile_src_path, profile_dst_path) symlink_force(profile_src_path, profile_dst_path)
# Append command avd_path = '/'.join([ANDROID_HOME, 'android_emulator'])
cmd += ' -d {device} -s {skin}'.format(device=device_name_bash, skin=skin_name) creation_cmd = 'avdmanager create avd -f -n {name} -b {img_type}/{sys_img} -k "system-images;android-{api_lvl};' \
logger.info('AVD creation command: {cmd}'.format(cmd=cmd)) '{img_type};{sys_img}" -d {device} -p {path}'.format(name=avd_name, img_type=IMG_TYPE, sys_img=SYS_IMG,
subprocess.check_call(cmd, shell=True) api_lvl=API_LEVEL, device=device_name_bash,
path=avd_path)
logger.info('Command to create avd: {command}'.format(command=creation_cmd))
subprocess.check_call(creation_cmd, shell=True)
skin_path = '/'.join([ANDROID_HOME, 'devices', 'skins', skin_name])
config_path = '/'.join([avd_path, 'config.ini'])
with open(config_path, 'a') as file:
file.write('skin.path={sp}'.format(sp=skin_path))
logger.info('Skin was added in config.ini')
def appium_run(avd_name: str): def appium_run(avd_name: str):
@@ -176,8 +182,9 @@ def run():
logger.info('Preparing emulator...') logger.info('Preparing emulator...')
prepare_avd(device, avd_name) prepare_avd(device, avd_name)
logger.info('Run emulator...') logger.info('Run emulator...')
cmd = 'emulator -avd {name}'.format(name=avd_name) cmd = 'emulator -avd {name} -gpu off'.format(name=avd_name)
subprocess.Popen(cmd.split()) subprocess.Popen(cmd.split())
appium = convert_str_to_bool(str(os.getenv('APPIUM', False))) appium = convert_str_to_bool(str(os.getenv('APPIUM', False)))
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
if [ -z $REAL_DEVICE ]; then
python3 -m src.app
else
CMD="appium"
if [ ! -z "$CONNECT_TO_GRID" ]; then
NODE_CONFIG_JSON="/root/src/nodeconfig.json"
/root/generate_config.sh $NODE_CONFIG_JSON
CMD+=" --nodeconfig $NODE_CONFIG_JSON"
fi
$CMD
fi
+8
View File
@@ -0,0 +1,8 @@
#!/bin/bash
if [ -z "$REAL_DEVICE"]; then
echo "Container is using android emulator"
else
echo "Starting android screen mirro..."
java -jar /root/asm.jar $ANDROID_HOME
fi
+47
View File
@@ -0,0 +1,47 @@
#!/bin/bash
function start() {
mkdir -p $VIDEO_PATH
name="$(date '+%d_%m_%Y_%H_%M_%S').mp4"
echo "Start video recording"
ffmpeg -video_size 1599x899 -framerate 15 -f x11grab -i $DISPLAY $VIDEO_PATH/$name -y
}
function stop() {
echo "Stop video recording"
kill $(ps -ef | grep [f]fmpeg | awk '{print $2}')
}
function auto_record() {
echo "Auto record: $AUTO_RECORD"
sleep 6
while [ $AUTO_RECORD == "True" ]; do
# Check if there is test running
no_test=true
while $no_test; do
task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value')
if [ "$task" == "" ] || [ "$task" == "[]" ]; then
sleep .5
else
start &
no_test=false
fi
done
# Check if test is finished
while [ $no_test == false ]; do
task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value')
if [ "$task" == "" ] || [ "$task" == "[]" ]; then
stop
no_test=true
else
sleep .5
fi
done
done
echo "Auto recording is disabled!"
}
$@
+19
View File
@@ -10,6 +10,25 @@ from src import app
class TestApp(TestCase): class TestApp(TestCase):
"""Unit test class to test other methods in the app.""" """Unit test class to test other methods in the app."""
@classmethod
def test_symlink(self):
res = os.path.join('testFile1.txt')
dest = os.path.join('link_testFile1.txt')
open(res, 'a').close()
app.symlink_force(res, dest)
os.remove(res)
os.remove(dest)
@classmethod
def test_symlink_already_exist(self):
res = os.path.join('testFile1.txt')
dest = os.path.join('link_testFile1.txt')
open(res, 'a').close()
open(dest, 'a').close()
app.symlink_force(res, dest)
os.remove(res)
os.remove(dest)
def test_valid_env(self): def test_valid_env(self):
key = 'ENV_1' key = 'ENV_1'
os.environ[key] = 'test' os.environ[key] = 'test'
+17 -21
View File
@@ -8,34 +8,30 @@ from src import app
@mock.patch('subprocess.check_call') @mock.patch('subprocess.check_call')
@mock.patch('os.symlink')
class TestAvd(TestCase): class TestAvd(TestCase):
"""Unit test class to test method create_avd.""" """Unit test class to test method create_avd."""
def setUp(self): def setUp(self):
self.avd_name = 'test_avd' self.avd_name = 'test_avd'
def test_nexus_avd_as_default(self, mocked_suprocess, mocked_sys_link): @mock.patch("builtins.open", create=True)
with mock.patch('os.listdir') as mocked_list_dir: def test_nexus_avd_as_default(self, mocked_suprocess, mocked_open):
mocked_list_dir.return_value = ['file1', 'file2'] self.assertFalse(mocked_suprocess.called)
self.assertFalse(mocked_list_dir.called) self.assertFalse(mocked_open.called)
self.assertFalse(mocked_sys_link.called) app.prepare_avd('Nexus 5', self.avd_name)
self.assertFalse(mocked_suprocess.called) self.assertTrue(mocked_suprocess.called)
app.prepare_avd('Nexus 5', self.avd_name) self.assertTrue(mocked_open.called)
self.assertTrue(mocked_list_dir.called)
self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_suprocess.called)
def test_samsung_avd(self, mocked_suprocess, mocked_sys_link): @mock.patch('os.symlink')
with mock.patch('os.listdir') as mocked_list_dir: @mock.patch("builtins.open", create=True)
mocked_list_dir.return_value = ['file1', 'file2'] def test_samsung_avd(self, mocked_suprocess, mocked_sys_link, mocked_open):
self.assertFalse(mocked_list_dir.called) self.assertFalse(mocked_sys_link.called)
self.assertFalse(mocked_sys_link.called) self.assertFalse(mocked_suprocess.called)
self.assertFalse(mocked_suprocess.called) self.assertFalse(mocked_open.called)
app.prepare_avd('Samsung Galaxy S6', self.avd_name) app.prepare_avd('Samsung Galaxy S6', self.avd_name)
self.assertTrue(mocked_list_dir.called) self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_sys_link.called) self.assertTrue(mocked_suprocess.called)
self.assertTrue(mocked_suprocess.called) self.assertTrue(mocked_open.called)
def tearDown(self): def tearDown(self):
if os.getenv('DEVICE'): if os.getenv('DEVICE'):
+24 -1
View File
@@ -2,33 +2,56 @@
nodaemon=true nodaemon=true
logfile=%(ENV_LOG_PATH)s/supervisord.log logfile=%(ENV_LOG_PATH)s/supervisord.log
childlogdir=%(ENV_LOG_PATH)s childlogdir=%(ENV_LOG_PATH)s
priority=1
[program:xvfb] [program:xvfb]
command=/usr/bin/Xvfb %(ENV_DISPLAY)s -screen %(ENV_SCREEN)s %(ENV_SCREEN_WIDTH)sx%(ENV_SCREEN_HEIGHT)sx%(ENV_SCREEN_DEPTH)s command=/usr/bin/Xvfb %(ENV_DISPLAY)s -screen %(ENV_SCREEN)s %(ENV_SCREEN_WIDTH)sx%(ENV_SCREEN_HEIGHT)sx%(ENV_SCREEN_DEPTH)s
stdout_logfile=%(ENV_LOG_PATH)s/xvfb.stdout.log stdout_logfile=%(ENV_LOG_PATH)s/xvfb.stdout.log
stderr_logfile=%(ENV_LOG_PATH)s/xvfb.stderr.log stderr_logfile=%(ENV_LOG_PATH)s/xvfb.stderr.log
priority=1
[program:openbox] [program:openbox]
command=/usr/bin/openbox-session command=/usr/bin/openbox-session
stdout_logfile=%(ENV_LOG_PATH)s/openbox.stdout.log stdout_logfile=%(ENV_LOG_PATH)s/openbox.stdout.log
stderr_logfile=%(ENV_LOG_PATH)s/openbox.stderr.log stderr_logfile=%(ENV_LOG_PATH)s/openbox.stderr.log
priority=2
[program:x11vnc] [program:x11vnc]
command=/usr/bin/x11vnc -display %(ENV_DISPLAY)s -nopw -forever -shared command=/usr/bin/x11vnc -display %(ENV_DISPLAY)s -nopw -forever -shared
stdout_logfile=%(ENV_LOG_PATH)s/x11vnc.stdout.log stdout_logfile=%(ENV_LOG_PATH)s/x11vnc.stdout.log
stderr_logfile=%(ENV_LOG_PATH)s/x11vnc.stderr.log stderr_logfile=%(ENV_LOG_PATH)s/x11vnc.stderr.log
priority=2
[program:novnc] [program:novnc]
command=./noVNC/utils/launch.sh --vnc localhost:%(ENV_LOCAL_PORT)s --listen %(ENV_TARGET_PORT)s command=./noVNC/utils/launch.sh --vnc localhost:%(ENV_LOCAL_PORT)s --listen %(ENV_TARGET_PORT)s
stdout_logfile=%(ENV_LOG_PATH)s/novnc.stdout.log stdout_logfile=%(ENV_LOG_PATH)s/novnc.stdout.log
stderr_logfile=%(ENV_LOG_PATH)s/novnc.stderr.log stderr_logfile=%(ENV_LOG_PATH)s/novnc.stderr.log
priority=2
[program:port-forward] [program:port-forward]
command=./src/port_forward.sh command=./src/port_forward.sh
autorestart=false autorestart=false
priority=1
;startsecs to fix "not expected" error. see: https://github.com/Supervisor/supervisor/issues/212#issuecomment-47933372
[program:android-screen-mirror]
command=./src/asm.sh
autorestart=false
startsecs=0
stdout_logfile=%(ENV_LOG_PATH)s/android-screen-mirror.stdout.log
stderr_logfile=%(ENV_LOG_PATH)s/android-screen-mirror.stderr.log
priority=3
[program:docker-appium] [program:docker-appium]
command=python3 -m src.app command=./src/appium.sh
autorestart=false autorestart=false
stdout_logfile=%(ENV_LOG_PATH)s/docker-android.stdout.log stdout_logfile=%(ENV_LOG_PATH)s/docker-android.stdout.log
stderr_logfile=%(ENV_LOG_PATH)s/docker-android.stderr.log stderr_logfile=%(ENV_LOG_PATH)s/docker-android.stderr.log
priority=4
[program:auto-recording]
command=./src/record.sh auto_record
autorestart=false
stdout_logfile=%(ENV_LOG_PATH)s/video-recording.stdout.log
stderr_logfile=%(ENV_LOG_PATH)s/video-recording.stderr.log
priority=4
+9 -4
View File
@@ -5,10 +5,15 @@ if [ -z "$TRAVIS_TAG" ]; then
echo "UNIT TEST ONLY" echo "UNIT TEST ONLY"
bash release.sh test all all 0.1 bash release.sh test all all 0.1
else else
echo "Log in to docker hub" if [ ! -z "$ANDROID_VERSION" ]; then
docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD" echo "Log in to docker hub"
echo "[Version: $ANDROID_VERSION] RUN UNIT TEST, BUILD DOCKER IMAGES AND PUSH THOSE TO DOCKER HUB" docker login -u="$DOCKER_USERNAME" -p="$DOCKER_PASSWORD"
bash release.sh all $ANDROID_VERSION all $TRAVIS_TAG echo "[Version: $ANDROID_VERSION] RUN UNIT TEST, BUILD DOCKER IMAGES AND PUSH THOSE TO DOCKER HUB"
bash release.sh all $ANDROID_VERSION all $TRAVIS_TAG
elif [ ! -z "$REAL_DEVICE" ]; then
echo "[SUPPORT FOR REAL DEVICE: BUILD DOCKER IMAGES AND PUSH THOSE TO DOCKER HUB ]"
bash release_real.sh all $TRAVIS_TAG
fi
echo "Log out of docker hub" echo "Log out of docker hub"
docker logout docker logout
fi fi