diff --git a/Dockerfile b/Dockerfile index 06b3f97..90aa1b6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,7 +49,6 @@ RUN echo y | android update sdk --no-ui --filter 2,3 ENV PATH="${PATH}:${ANDROID_HOME}/platform-tools" ENV PATH="${PATH}:${ANDROID_HOME}/build-tools" RUN mv ${ANDROID_HOME}/tools/emulator ${ANDROID_HOME}/tools/emulator.backup -RUN ln -s ${ANDROID_HOME}/tools/emulator64-arm ${ANDROID_HOME}/tools/emulator #==================================== # Install latest nodejs, npm, appium @@ -60,6 +59,12 @@ RUN apt-get install nodejs -y ENV APPIUM_VERSION 1.6.3 RUN npm install -g appium@$APPIUM_VERSION +#============================================================ +# Install KVM for emulator x86 +# Source: https://help.ubuntu.com/community/KVM/Installation +#============================================================ +RUN apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils -y + #====================== # noVNC Configurations #====================== @@ -73,6 +78,12 @@ ENV DISPLAY=:0 \ TIMEOUT=1 RUN ln -s noVNC/vnc_auto.html noVNC/index.html +#============== +# Expose Ports +#============== +EXPOSE 4723 +EXPOSE 6080 + #=================== # Run docker-appium #=================== diff --git a/README.md b/README.md index 4a2d898..25d11bb 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,22 @@ Docker is installed in your system. Quick Start ----------- -1. Run docker-appium with command: +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: ```bash - docker run -d -p 6080:6080 -p 4723:4723 -v :/target_apk -e ANDROID_VERSION= --name appium-container butomo1989/docker-appium + docker run -d -p 6080:6080 -p 4723:4723 -v :/target_apk -e ANDROID_VERSION= -e EMULATOR_TYPE= --name appium-container butomo1989/docker-appium ``` - ***Note: There is an example apk in folder "example".*** - 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 --name appium-container butomo1989/docker-appium + 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 --name appium-container butomo1989/docker-appium ``` + **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: diff --git a/service/start.py b/service/start.py index 33da529..dbfdac2 100644 --- a/service/start.py +++ b/service/start.py @@ -6,23 +6,37 @@ import subprocess logging.basicConfig() logger = logging.getLogger('android_appium') +# not using enum because need to install pip that will make docker image size bigger +TYPE_ARMEABI = 'armeabi' +TYPE_X86 = 'x86' + def run(): """ Start noVNC, installation of needed android SDK packages and Appium server. """ + # Get android version package android_version = os.getenv('ANDROID_VERSION', '4.2.2') os.environ['emulator_name'] = 'emulator_{version}'.format(version=android_version) + # Get emulator type + types = [TYPE_ARMEABI, TYPE_X86] + emulator_type = os.getenv('EMULATOR_TYPE', TYPE_ARMEABI).lower() + emulator_type = TYPE_ARMEABI if emulator_type not in types else emulator_type + + # Link emulator shortcut + subprocess.check_call('ln -s $ANDROID_HOME/tools/{shortcut_file} $ANDROID_HOME/tools/emulator'.format( + shortcut_file='emulator64-x86' if emulator_type == TYPE_X86 else 'emulator64-arm'), shell=True) + # Start Xvfb subprocess.check_call('Xvfb ${DISPLAY} -screen ${SCREEN} ${SCREEN_WIDTH}x${SCREEN_HEIGHT}x${SCREEN_DEPTH} & ' 'sleep ${TIMEOUT}', shell=True) - # Start noVNC, installation of packages and appium + # Start noVNC, installation of android packages, emulator creation and appium vnc_cmd = 'openbox-session & x11vnc -display ${DISPLAY} -nopw -ncache 10 -forever & ' \ './noVNC/utils/launch.sh --vnc localhost:${LOCAL_PORT} --listen ${TARGET_PORT}' - android_cmd = get_android_bash_commands(android_version) + android_cmd = get_android_bash_commands(android_version, emulator_type) if android_cmd: cmd = '({vnc}) & (xterm -T "Android-Appium" -n "Android-Appium" -e \"{android} && ' \ '/bin/echo $emulator_name && appium\")'.format(vnc=vnc_cmd, android=android_cmd) @@ -61,15 +75,17 @@ def get_item_position(keyword, items): return pos -def get_android_bash_commands(android_version): +def get_android_bash_commands(android_version, emulator_type): """ - Get bash commands to install given android version and to create android emulator. + Get bash commands to install given android version and to create android emulator based on given type. To see list of available targets: android list targets To see list to avd: android list avd :param android_version: android version :type android_version: str + :param emulator_type: emulator type + :type emulator_type: str :return: bash commands :rtype: bytearray """ @@ -90,17 +106,17 @@ def get_android_bash_commands(android_version): 'Package number: {number}, API version: {version}'.format(number=package_number, version=api_version)) commands = [] + # Command to install SDK package commands.append('echo y | android update sdk --no-ui --filter {number}'.format(number=package_number)) - # Command to install armeabi v7a - commands.append('echo y | android update sdk --no-ui -a --filter sys-img-armeabi-v7a-android-{api}'.format( - api=api_version)) - - # Command to create android emulator + # Command to install system image and create android emulator + sys_img = 'x86' if emulator_type == TYPE_X86 else 'armeabi-v7a' + commands.append('echo y | android update sdk --no-ui -a --filter sys-img-{sys_img}-android-{api}'.format( + sys_img=sys_img, api=api_version)) commands.append( - 'echo no | android create avd -f -n emulator_{version} -t android-{api} --abi armeabi-v7a'.format( - version=android_version, api=api_version)) + 'echo no | android create avd -f -n emulator_{version} -t android-{api} --abi {sys_img}'.format( + version=android_version, api=api_version, sys_img=sys_img)) # Join all commands in one str for xterm bash_command = ' && '.join(commands) diff --git a/service/tests/test_get_command.py b/service/tests/test_get_command.py index ecf6547..8e48957 100644 --- a/service/tests/test_get_command.py +++ b/service/tests/test_get_command.py @@ -10,13 +10,15 @@ from service import start class TestRunService(TestCase): """Unit test class to test method get_android_bash_commands.""" + def setUp(self): + self.android_version = '4.2.2' + self.emulator_type = start.TYPE_ARMEABI + def test_create_emulator(self, mocked_packages): mocked_packages.return_value = ['9- SDK Platform Android 4.4.2, API 19, revision 4', '10- SDK Platform Android 4.3.1, API 18, revision 3', '11- SDK Platform Android 4.2.2, API 17, revision 3'] - - android_version = '4.2.2' - cmd = start.get_android_bash_commands(android_version) + cmd = start.get_android_bash_commands(self.android_version, self.emulator_type) self.assertIsNotNone(cmd) self.assertTrue('android update sdk' in cmd) self.assertTrue('android create avd' in cmd) @@ -24,12 +26,11 @@ class TestRunService(TestCase): def test_empty_packages(self, mocked_packages): mocked_packages.return_value = None with self.assertRaises(RuntimeError): - start.get_android_bash_commands('4.2.2') + start.get_android_bash_commands(self.android_version, self.emulator_type) def test_index_error(self, mocked_packages): mocked_packages.return_value = ['9 SDK Platform Android 4.4.2, API 19, revision 4', '10 SDK Platform Android 4.3.1, API 18, revision 3', '11 SDK Platform Android 4.2.2, API 17, revision 3'] - android_version = '4.2.2' - start.get_android_bash_commands(android_version) + start.get_android_bash_commands(self.android_version, self.emulator_type) self.assertRaises(IndexError)