diff --git a/README.md b/README.md index b4cd08e..df53d99 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Docker is installed in your system. Features -------- -1. Android emulator +1. Android emulator with different devices / skins 2. noVNC 3. Appium server 4. Able to connect to selenium grid @@ -28,26 +28,22 @@ Quick Start 1. Enable **Virtualization** under **System Setup** in **BIOS**. (It is only for Ubuntu OS. If you use different OS, you can skip this step). -2. Run docker-appium with command: +2. Run docker-appium. + + **Optional arguments** + + --privileged : Only for ubuntu OS. This flag allow to use system image x86 for better performance + -v :/target_apk : Path of android apk that want to be tested + -e DEVICE="" : Device name. Default device is Nexus 5 + -e ANDROID_VERSION=: Android version of emulator. Default android version is 5.0 + -e EMULATOR_TYPE= : Emulator system image. Default system image is armeabi + + **An Example command to run docker-appium under linux** ```bash - docker run -d -p 6080:6080 -p 4723:4723 -v :/target_apk -e ANDROID_VERSION= -e EMULATOR_TYPE= -e CONNECT_TO_GRID= --name appium-container butomo1989/docker-appium + docker run --privileged -d -p 6080:6080 -p 4723:4723 -v $PWD/example/sample_apk:/target_apk -e DEVICE="Nexus 5" -e ANDROID_VERSION=5.0 -e EMULATOR_TYPE=armeabi --name appium-container butomo1989/docker-appium ``` - An Example: - - ```bash - docker run -d -p 6080:6080 -p 4723:4723 -v $PWD/example/sample_apk:/target_apk -e ANDROID_VERSION=4.2.2 -e EMULATOR_TYPE=armeabi -e CONNECT_TO_GRID=False --name appium-container butomo1989/docker-appium - ``` - **Optional arguments for CONNECT\_TO\_GRID=True** - - -e APPIUM_HOST="": if appium is running under different host. default value: 127.0.0.1 - -e APPIUM_PORT=: if appium is running under different port. default port: 4723 - -e SELENIUM_HOST="": if selenium hub is running under different host. default value: 172.17.0.1 - -e SELENIUM_PORT=: if selenium hub is running under different port. default port: 4444 - - **Note: use flag *--privileged* and *EMULATOR_TYPE=x86* for ubuntu OS to make emulator faster** - 2. Verify the ip address of docker-machine. - For OSX, you can find out by using following command: @@ -58,7 +54,7 @@ Quick Start - For different OS, localhost should work. -3. Open ***http://docker-machine-ip-address:6080/vnc.html*** from web browser and connect to it without password. +3. Open ***http://docker-machine-ip-address:6080/vnc.html*** from web browser. ![][noVNC] @@ -66,17 +62,60 @@ Quick Start ![][Appium is ready] - *The name of created emulator can be seen in that terminal. In screenshot above, the emulator name is* ***emulator_4.2.2***. + *The name of created emulator can be seen in that terminal. In screenshot above, the emulator name is* ***nexus\_5_5.0***. 5. Run your UI tests by using docker-appium and Android emulator will be started automatically by following desire capability: ``` desired_caps = { - 'avd': 'emulator_4.2.2' + 'avd': 'nexus_5_5.0' } ``` ***Note: In folder "example" there is an example of Appium-UITest that is written in python.*** +Connect to Selenium Grid +------------------------ +pass environment variable **CONNECT\_TO\_GRID=True** to connect docker-appium to your selenium grid. + +**Optional arguments** + + -e APPIUM_HOST="" : where / on which instance is appium server running. Default value: 127.0.0.1 + -e APPIUM_PORT= : which port is appium server running. Default port: 4723 + -e SELENIUM_HOST="" : where / on which instance is selenium grid running. Default value: 172.17.0.1 + -e SELENIUM_PORT= : which port is selenium grid running. default port: 4444 + +![][connect to grid 1] ![][connect to grid 2] + +List of Devices +--------------- +Type | Device Name +--- | --- +Phone | Galaxy Nexus +Phone | Nexus 4 +Phone | Nexus 5 +Phone | Nexus 5x +Phone | Nexus 6 +Phone | Nexus 6P +Phone | Nexus One +Phone | Nexus S +Tablet | Pixel C +Tablet | Nexus 7 +Tablet | Nexus 9 +Tablet | Nexus 10 + +![][nexus 5] + +Troubleshooting +--------------- +All logs inside container are stored under folder **/var/log/supervisor**. you can print out log file by using **docker exec**. Example: + +```bash +docker exec -it appium-container tail -f /var/log/supervisor/docker-appium.stdout.log +``` + [noVNC]: "login with noVNC to see what happen inside container" [Appium is ready]: "appium is ready" +[connect to grid 1]: +[connect to grid 2]: +[nexus 5]: diff --git a/images/appium.png b/images/appium.png index aa5146a..0589bb8 100644 Binary files a/images/appium.png and b/images/appium.png differ diff --git a/images/appium_with_selenium_grid_01.png b/images/appium_with_selenium_grid_01.png new file mode 100644 index 0000000..a498490 Binary files /dev/null and b/images/appium_with_selenium_grid_01.png differ diff --git a/images/appium_with_selenium_grid_02.png b/images/appium_with_selenium_grid_02.png new file mode 100644 index 0000000..28f4fc2 Binary files /dev/null and b/images/appium_with_selenium_grid_02.png differ diff --git a/images/noVNC.png b/images/noVNC.png index c4ba976..f3db055 100644 Binary files a/images/noVNC.png and b/images/noVNC.png differ diff --git a/images/run_under_nexus_5.png b/images/run_under_nexus_5.png new file mode 100644 index 0000000..86f7457 Binary files /dev/null and b/images/run_under_nexus_5.png differ diff --git a/skins/nexus_7_2013/land_back.png b/skins/nexus_7_2013/land_back.png deleted file mode 100644 index c88c18f..0000000 Binary files a/skins/nexus_7_2013/land_back.png and /dev/null differ diff --git a/skins/nexus_7_2013/land_fore.png b/skins/nexus_7_2013/land_fore.png deleted file mode 100644 index e49b1cd..0000000 Binary files a/skins/nexus_7_2013/land_fore.png and /dev/null differ diff --git a/skins/nexus_7_2013/land_shadow.png b/skins/nexus_7_2013/land_shadow.png deleted file mode 100644 index aaf1058..0000000 Binary files a/skins/nexus_7_2013/land_shadow.png and /dev/null differ diff --git a/skins/nexus_7_2013/layout b/skins/nexus_7_2013/layout deleted file mode 100644 index fb8983b..0000000 --- a/skins/nexus_7_2013/layout +++ /dev/null @@ -1,59 +0,0 @@ -parts { - device { - display { - width 1200 - height 1920 - x 0 - y 0 - } - } - portrait { - background { - image port_back.png - } - onion { - image port_fore.png - } - } - landscape { - background { - image land_back.png - } - onion { - image land_fore.png - } - } -} -layouts { - portrait { - width 1596 - height 2571 - event EV_SW:0:1 - part1 { - name portrait - x 0 - y 0 - } - part2 { - name device - x 195 - y 301 - } - } - landscape { - width 2772 - height 1479 - event EV_SW:0:0 - part1 { - name landscape - x 0 - y 0 - } - part2 { - name device - x 423 - y 1320 - rotation 3 - } - } -} diff --git a/skins/nexus_7_2013/port_back.png b/skins/nexus_7_2013/port_back.png deleted file mode 100644 index e7f9e98..0000000 Binary files a/skins/nexus_7_2013/port_back.png and /dev/null differ diff --git a/skins/nexus_7_2013/port_fore.png b/skins/nexus_7_2013/port_fore.png deleted file mode 100644 index d348dde..0000000 Binary files a/skins/nexus_7_2013/port_fore.png and /dev/null differ diff --git a/skins/nexus_7_2013/port_shadow.png b/skins/nexus_7_2013/port_shadow.png deleted file mode 100644 index bea7a24..0000000 Binary files a/skins/nexus_7_2013/port_shadow.png and /dev/null differ diff --git a/skins/source.txt b/skins/source.txt new file mode 100644 index 0000000..4d5d74e --- /dev/null +++ b/skins/source.txt @@ -0,0 +1 @@ +copied from Android Studio IDE \ No newline at end of file diff --git a/src/android.py b/src/android.py index be84ca8..389efa0 100644 --- a/src/android.py +++ b/src/android.py @@ -28,8 +28,7 @@ def get_api_level(android_version): item_info = item.split('-') api_version = re.search('%s(.*)%s' % ('API', ','), item_info[1]).group(1).strip() - logger.info( - 'API level: {api}'.format(api=api_version)) + logger.info('API level: {api}'.format(api=api_version)) else: raise RuntimeError('List of packages is empty!') @@ -64,12 +63,16 @@ def install_package(android_path, emulator_file, api_level, sys_img): subprocess.check_call('xterm -e \"{cmd}\"'.format(cmd=cmd), shell=True) -def create_avd(android_path, avd_name, api_level): +def create_avd(android_path, device, skin, avd_name, api_level): """ Create android virtual device. :param android_path: location where android SDK is installed :type android_path: str + :param device: name of device + :type device: str + :param skin: emulator skin that want to be used + :type skin: str :param avd_name: desire name :type avd_name: str :param api_level: api level @@ -83,6 +86,8 @@ def create_avd(android_path, avd_name, api_level): # Create android emulator cmd = 'echo no | android create avd -f -n {name} -t android-{api}'.format(name=avd_name, api=api_level) + if device and skin: + cmd += ' -d {device} -s {skin}'.format(device=device.replace(' ', '\ '), skin=skin) logger.info('Emulator creation command : {cmd}'.format(cmd=cmd)) subprocess.check_call('xterm -e \"{cmd}\"'.format(cmd=cmd), shell=True) diff --git a/src/service.py b/src/service.py index c3aba6d..578036b 100644 --- a/src/service.py +++ b/src/service.py @@ -30,14 +30,18 @@ def start(): emulator_file = 'emulator64-x86' if emulator_type == TYPE_X86 else 'emulator64-arm' logger.info('Emulator file: {file}'.format(file=emulator_file)) api_level = android.get_api_level(android_version) - sys_img = 'x86' if emulator_type == TYPE_X86 else 'armeabi-v7a' + sys_img = 'x86_64' if emulator_type == TYPE_X86 else 'armeabi-v7a' logger.info('System image: {sys_img}'.format(sys_img=sys_img)) android.install_package(android_path, emulator_file, api_level, sys_img) # Create android virtual device - avd_name = 'emulator_{version}'.format(version=android_version) + device_name = os.getenv('DEVICE', 'Nexus 5') + logger.info('Device: {device}'.format(device=device_name)) + skin_name = device_name.replace(' ', '_').lower() + logger.info('Skin: {skin}'.format(skin=skin_name)) + avd_name = '{device}_{version}'.format(device=skin_name, version=android_version) logger.info('AVD name: {avd}'.format(avd=avd_name)) - android.create_avd(android_path, avd_name, api_level) + android.create_avd(android_path, device_name, skin_name, avd_name, api_level) # Run appium server appium.run(connect_to_grid, avd_name, android_version) diff --git a/src/tests/android/test_create_avd.py b/src/tests/android/test_create_avd.py index b975ccc..7678b0c 100644 --- a/src/tests/android/test_create_avd.py +++ b/src/tests/android/test_create_avd.py @@ -11,7 +11,9 @@ class TestAvd(TestCase): def setUp(self): self.android_path = '/root' - self.avd_name = 'test' + self.device = 'Nexus\ 5' + self.skin = 'nexus_5' + self.avd_name = 'nexus_5_5.0' self.api_level = 21 @mock.patch('os.symlink') @@ -22,7 +24,7 @@ class TestAvd(TestCase): self.assertFalse(mocked_list_dir.called) self.assertFalse(mocked_sys_link.called) self.assertFalse(mocked_suprocess.called) - android.create_avd(self.android_path, self.avd_name, self.api_level) + android.create_avd(self.android_path, self.device, self.skin, self.avd_name, self.api_level) self.assertTrue(mocked_list_dir.called) self.assertTrue(mocked_sys_link.called) self.assertTrue(mocked_suprocess.called) diff --git a/src/tests/appium/test_run.py b/src/tests/appium/test_run.py index 77c7ac3..c92219a 100644 --- a/src/tests/appium/test_run.py +++ b/src/tests/appium/test_run.py @@ -1,7 +1,6 @@ """Unit test for appium.py.""" -from unittest import TestCase - import os +from unittest import TestCase import mock diff --git a/supervisord.conf b/supervisord.conf index d183a7d..d0a6eed 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -25,5 +25,6 @@ stderr_logfile=%(ENV_LOG_PATH)s/novnc.stderr.log [program:docker-appium] command=python -m src.service +autorestart=false stdout_logfile=%(ENV_LOG_PATH)s/docker-appium.stdout.log stderr_logfile=%(ENV_LOG_PATH)s/docker-appium.stderr.log