diff --git a/README.md b/README.md index 2ab0cc9..cf55f58 100644 --- a/README.md +++ b/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. 3. Ability to connect to Selenium Grid 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 --------------------- @@ -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|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")| +|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 --------------- @@ -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 ``` +### 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 ![][compose] @@ -202,6 +209,7 @@ docker exec -it android-container tail -f /var/log/supervisor/docker-android.std [docker android nexus]: [compose]: [connected_devices]: +[line]: [example of compose file]: [docker-compose]: [1.13.0]: diff --git a/docker-compose.yml b/docker-compose.yml index edae1cb..3780c3e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,14 +14,13 @@ services: nexus_7.1.1: image: butomo1989/docker-android-x86-7.1.1 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 scale: 1 ports: - 6080 + # 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 - ./video-nexus_7.1.1:/tmp/video environment: - DEVICE=Nexus 5 diff --git a/docker/Emulator_arm b/docker/Emulator_arm index 58e05a6..0cb4ab8 100644 --- a/docker/Emulator_arm +++ b/docker/Emulator_arm @@ -34,6 +34,8 @@ WORKDIR /root #------------------ # ffmpeg # Video recorder +# jq +# Sed for JSON data #================== RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \ xterm \ @@ -45,6 +47,7 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \ python-numpy \ net-tools \ ffmpeg \ + jq \ && rm -rf /var/lib/apt/lists/* #======= diff --git a/docker/Emulator_x86 b/docker/Emulator_x86 index 7460f83..9576f40 100644 --- a/docker/Emulator_x86 +++ b/docker/Emulator_x86 @@ -34,6 +34,8 @@ WORKDIR /root #------------------ # ffmpeg # Video recorder +# jq +# Sed for JSON data #------------------ # KVM Package # for emulator x86 @@ -54,6 +56,7 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \ python-numpy \ net-tools \ ffmpeg \ + jq \ qemu-kvm \ libvirt-bin \ ubuntu-vm-builder \ diff --git a/docker/Real_device b/docker/Real_device index 077183f..a882c0e 100644 --- a/docker/Real_device +++ b/docker/Real_device @@ -34,6 +34,8 @@ WORKDIR /root #------------------ # ffmpeg # Video recorder +# jq +# Sed for JSON data #================== RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \ xterm \ @@ -45,6 +47,7 @@ RUN apt-get -qqy update && apt-get -qqy install --no-install-recommends \ python-numpy \ net-tools \ ffmpeg \ + jq \ && rm -rf /var/lib/apt/lists/* #======= diff --git a/src/app.py b/src/app.py index de493a2..aeaad8a 100644 --- a/src/app.py +++ b/src/app.py @@ -4,6 +4,7 @@ import json import logging import os import subprocess +import errno from src import CONFIG_FILE, ROOT, CHROME_DRIVER from src import log @@ -11,6 +12,13 @@ from src import log log.init() 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: """ @@ -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') 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)) + symlink_force(os.path.join(skin_rsc_path, s), os.path.join(skin_dst_path, s)) # Hardware and its skin 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)) logger.info('Hardware profile resource path: {rsc}'.format(rsc=profile_src_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 cmd += ' -d {device} -s {skin}'.format(device=device_name_bash, skin=skin_name) diff --git a/src/record.sh b/src/record.sh index dc1a614..e4c39bb 100644 --- a/src/record.sh +++ b/src/record.sh @@ -2,44 +2,46 @@ function start() { mkdir -p $VIDEO_PATH - sw=$(($SCREEN_WIDTH - 1)) - sh=$(($SCREEN_HEIGHT - 1)) - name="$DEVICE-$BROWSER-$(date '+%d/%m/%Y-%H:%M:%S')" + name="$(date '+%d_%m_%Y_%H_%M_%S').mp4" 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() { echo "Stop video recording" - kill $(ps -ef | grep ffmpeg) + kill $(ps -ef | grep [f]fmpeg | awk '{print $2}') } function auto_record() { - if [ ! -z $AUTO_RECORD ]; then - if [ ${AUTO_RECORD,,} = true ]; then - echo "Auto recording is enable. It will record the video automatically as soon as appium receive test scenario!" + echo "Auto record: $AUTO_RECORD" + sleep 6 - # 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 [ -n "$task" ]; then - sleep .5 - else - no_test=false - start - fi - done + 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 [ -n "$task" ]; then - stop - else - sleep .5 - fi - done - fi - fi -} \ No newline at end of file + # 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!" +} + +$@ diff --git a/src/tests/unit/test_app.py b/src/tests/unit/test_app.py index 93c555e..c31ac2d 100644 --- a/src/tests/unit/test_app.py +++ b/src/tests/unit/test_app.py @@ -10,6 +10,23 @@ from src import app class TestApp(TestCase): """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): key = 'ENV_1' os.environ[key] = 'test' diff --git a/supervisord.conf b/supervisord.conf index f865fd6..1e206a2 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -50,7 +50,7 @@ stderr_logfile=%(ENV_LOG_PATH)s/docker-android.stderr.log priority=4 [program:auto-recording] -command=./src/record.sh +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