Merge remote-tracking branch 'origin' into update-sdk
This commit is contained in:
commit
7a052b7e2f
10
README.md
10
README.md
|
@ -28,7 +28,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
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -45,6 +47,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
|
||||||
---------------
|
---------------
|
||||||
|
@ -127,6 +130,10 @@ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Share Volume
|
||||||
|
|
||||||
|
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]
|
||||||
|
@ -202,6 +209,7 @@ docker exec -it android-container tail -f /var/log/supervisor/docker-android.std
|
||||||
[docker android nexus]: <images/docker_android_nexus.png>
|
[docker android nexus]: <images/docker_android_nexus.png>
|
||||||
[compose]: <images/compose.png>
|
[compose]: <images/compose.png>
|
||||||
[connected_devices]: <images/connected_devices.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>
|
||||||
|
|
|
@ -14,14 +14,13 @@ services:
|
||||||
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
|
||||||
# Change path of apk that you want to test. I use sample_apk that I provide in folder "example"
|
|
||||||
volumes:
|
|
||||||
- $PWD/example/sample_apk:/root/tmp
|
|
||||||
# Increase scale number if needed
|
# Increase scale number if needed
|
||||||
scale: 1
|
scale: 1
|
||||||
ports:
|
ports:
|
||||||
- 6080
|
- 6080
|
||||||
|
# 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
|
||||||
- ./video-nexus_7.1.1:/tmp/video
|
- ./video-nexus_7.1.1:/tmp/video
|
||||||
environment:
|
environment:
|
||||||
- DEVICE=Nexus 5
|
- DEVICE=Nexus 5
|
||||||
|
|
|
@ -34,6 +34,8 @@ WORKDIR /root
|
||||||
#------------------
|
#------------------
|
||||||
# ffmpeg
|
# ffmpeg
|
||||||
# Video recorder
|
# 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 \
|
||||||
|
@ -45,6 +47,7 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
|
||||||
python-numpy \
|
python-numpy \
|
||||||
net-tools \
|
net-tools \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
|
jq \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
#=======
|
#=======
|
||||||
|
|
|
@ -34,6 +34,8 @@ WORKDIR /root
|
||||||
#------------------
|
#------------------
|
||||||
# ffmpeg
|
# ffmpeg
|
||||||
# Video recorder
|
# Video recorder
|
||||||
|
# jq
|
||||||
|
# Sed for JSON data
|
||||||
#------------------
|
#------------------
|
||||||
# KVM Package
|
# KVM Package
|
||||||
# for emulator x86
|
# for emulator x86
|
||||||
|
@ -54,6 +56,7 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
|
||||||
python-numpy \
|
python-numpy \
|
||||||
net-tools \
|
net-tools \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
|
jq \
|
||||||
qemu-kvm \
|
qemu-kvm \
|
||||||
libvirt-bin \
|
libvirt-bin \
|
||||||
ubuntu-vm-builder \
|
ubuntu-vm-builder \
|
||||||
|
|
|
@ -34,6 +34,8 @@ WORKDIR /root
|
||||||
#------------------
|
#------------------
|
||||||
# ffmpeg
|
# ffmpeg
|
||||||
# Video recorder
|
# 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 \
|
||||||
|
@ -45,6 +47,7 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \
|
||||||
python-numpy \
|
python-numpy \
|
||||||
net-tools \
|
net-tools \
|
||||||
ffmpeg \
|
ffmpeg \
|
||||||
|
jq \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
#=======
|
#=======
|
||||||
|
|
12
src/app.py
12
src/app.py
|
@ -4,6 +4,7 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import errno
|
||||||
|
|
||||||
from src import CONFIG_FILE, ROOT, CHROME_DRIVER
|
from src import CONFIG_FILE, ROOT, CHROME_DRIVER
|
||||||
from src import log
|
from src import log
|
||||||
|
@ -11,6 +12,13 @@ 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:
|
||||||
|
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:
|
||||||
"""
|
"""
|
||||||
|
@ -71,7 +79,7 @@ def prepare_avd(device: str, avd_name: str):
|
||||||
skin_dst_path = os.path.join(ANDROID_HOME, 'platforms', 'android-{api}'.format(api=API_LEVEL), 'skins')
|
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))
|
logger.info('Skin destination path: {dst}'.format(dst=skin_dst_path))
|
||||||
for s in os.listdir(skin_rsc_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))
|
symlink_force(os.path.join(skin_rsc_path, s), os.path.join(skin_dst_path, s))
|
||||||
|
|
||||||
# Hardware and its skin
|
# Hardware and its skin
|
||||||
device_name_bash = device.replace(' ', '\ ')
|
device_name_bash = device.replace(' ', '\ ')
|
||||||
|
@ -85,7 +93,7 @@ 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
|
# Append command
|
||||||
cmd += ' -d {device} -s {skin}'.format(device=device_name_bash, skin=skin_name)
|
cmd += ' -d {device} -s {skin}'.format(device=device_name_bash, skin=skin_name)
|
||||||
|
|
|
@ -2,44 +2,46 @@
|
||||||
|
|
||||||
function start() {
|
function start() {
|
||||||
mkdir -p $VIDEO_PATH
|
mkdir -p $VIDEO_PATH
|
||||||
sw=$(($SCREEN_WIDTH - 1))
|
name="$(date '+%d_%m_%Y_%H_%M_%S').mp4"
|
||||||
sh=$(($SCREEN_HEIGHT - 1))
|
|
||||||
name="$DEVICE-$BROWSER-$(date '+%d/%m/%Y-%H:%M:%S')"
|
|
||||||
echo "Start video recording"
|
echo "Start video recording"
|
||||||
ffmpeg -video_size $swx$sh -framerate 15 -f x11grab -i ${DISPLAY} $VIDEO_PATH/$name -y
|
ffmpeg -video_size 1599x899 -framerate 15 -f x11grab -i $DISPLAY $VIDEO_PATH/$name -y
|
||||||
}
|
}
|
||||||
|
|
||||||
function stop() {
|
function stop() {
|
||||||
echo "Stop video recording"
|
echo "Stop video recording"
|
||||||
kill $(ps -ef | grep ffmpeg)
|
kill $(ps -ef | grep [f]fmpeg | awk '{print $2}')
|
||||||
}
|
}
|
||||||
|
|
||||||
function auto_record() {
|
function auto_record() {
|
||||||
if [ ! -z $AUTO_RECORD ]; then
|
echo "Auto record: $AUTO_RECORD"
|
||||||
if [ ${AUTO_RECORD,,} = true ]; then
|
sleep 6
|
||||||
echo "Auto recording is enable. It will record the video automatically as soon as appium receive test scenario!"
|
|
||||||
|
|
||||||
# Check if there is test running
|
while [ $AUTO_RECORD == "True" ]; do
|
||||||
no_test=true
|
# Check if there is test running
|
||||||
while $no_test; do
|
no_test=true
|
||||||
task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value')
|
while $no_test; do
|
||||||
if [ -n "$task" ]; then
|
task=$(curl -s localhost:4723/wd/hub/sessions | jq -r '.value')
|
||||||
sleep .5
|
if [ "$task" == "" ] || [ "$task" == "[]" ]; then
|
||||||
else
|
sleep .5
|
||||||
no_test=false
|
else
|
||||||
start
|
start &
|
||||||
fi
|
no_test=false
|
||||||
done
|
fi
|
||||||
|
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 [ -n "$task" ]; then
|
if [ "$task" == "" ] || [ "$task" == "[]" ]; then
|
||||||
stop
|
stop
|
||||||
else
|
no_test=true
|
||||||
sleep .5
|
else
|
||||||
fi
|
sleep .5
|
||||||
done
|
fi
|
||||||
fi
|
done
|
||||||
fi
|
done
|
||||||
}
|
|
||||||
|
echo "Auto recording is disabled!"
|
||||||
|
}
|
||||||
|
|
||||||
|
$@
|
||||||
|
|
|
@ -10,6 +10,23 @@ 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."""
|
||||||
|
|
||||||
|
#create symlink
|
||||||
|
@classmethod
|
||||||
|
def test_symlink_correct(self):
|
||||||
|
os.mknod(os.path.join("./","testFile1.txt"))
|
||||||
|
app.symlink_force(os.path.join("./","testFile1.txt"),os.path.join("./","link_testFile1.txt"))
|
||||||
|
os.remove(os.path.join("./","testFile1.txt"))
|
||||||
|
os.remove(os.path.join("./","link_testFile1.txt"))
|
||||||
|
|
||||||
|
#link already exist
|
||||||
|
@classmethod
|
||||||
|
def test_symlink_already_exist(self):
|
||||||
|
os.mknod(os.path.join("./","testFile2.txt"))
|
||||||
|
os.mknod(os.path.join("./","link_testFile2.txt"))
|
||||||
|
app.symlink_force(os.path.join("./","testFile2.txt"),os.path.join("./","link_testFile2.txt"))
|
||||||
|
os.remove(os.path.join("./","testFile2.txt"))
|
||||||
|
os.remove(os.path.join("./","link_testFile2.txt"))
|
||||||
|
|
||||||
def test_valid_env(self):
|
def test_valid_env(self):
|
||||||
key = 'ENV_1'
|
key = 'ENV_1'
|
||||||
os.environ[key] = 'test'
|
os.environ[key] = 'test'
|
||||||
|
|
|
@ -50,7 +50,7 @@ stderr_logfile=%(ENV_LOG_PATH)s/docker-android.stderr.log
|
||||||
priority=4
|
priority=4
|
||||||
|
|
||||||
[program:auto-recording]
|
[program:auto-recording]
|
||||||
command=./src/record.sh
|
command=./src/record.sh auto_record
|
||||||
autorestart=false
|
autorestart=false
|
||||||
stdout_logfile=%(ENV_LOG_PATH)s/video-recording.stdout.log
|
stdout_logfile=%(ENV_LOG_PATH)s/video-recording.stdout.log
|
||||||
stderr_logfile=%(ENV_LOG_PATH)s/video-recording.stderr.log
|
stderr_logfile=%(ENV_LOG_PATH)s/video-recording.stderr.log
|
||||||
|
|
Loading…
Reference in a new issue