support noVNC

This commit is contained in:
butomo1989 2017-01-08 17:24:14 +01:00
parent 08b0e65216
commit 7785e56a2a
4 changed files with 111 additions and 64 deletions

View file

@ -1,24 +1,44 @@
FROM ubuntu:16.04 FROM ubuntu:14.04
#======================= #=======================
# General Configuration # General Configuration
#======================= #=======================
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get upgrade -y RUN apt-get update && apt-get upgrade -y
RUN apt-get install wget -y
#=====================================
# Install virtual display framebuffer
#=====================================
RUN apt-get install Xvfb x11vnc -y
#================================================
# Install Windows Manager, Debian Menu and Numpy
# https://github.com/novnc/websockify/issues/77
#================================================
RUN apt-get install openbox menu python-numpy -y
#======================
# Clone noVNC projects
#======================
RUN apt-get install git -y
WORKDIR /root
RUN git clone https://github.com/kanaka/noVNC.git && \
cd noVNC/utils && git clone https://github.com/kanaka/websockify websockify
#============== #==============
# Install Java # Install Java
#============== #==============
RUN apt-get install openjdk-8-jdk -y RUN apt-get install openjdk-7-jdk -y
ENV JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/jre" ENV JAVA_HOME="/usr/lib/jvm/java-7-openjdk-amd64/jre"
ENV PATH="${PATH}:${JAVA_HOME}/bin" ENV PATH="${PATH}:${JAVA_HOME}/bin"
#===================== #=====================
# Install Android SDK # Install Android SDK
#===================== #=====================
RUN apt-get install wget -y
RUN wget http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz RUN wget http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
RUN tar -xvzf android-sdk_r24.4.1-linux.tgz RUN tar -xvzf android-sdk_r24.4.1-linux.tgz && rm android-sdk_r24.4.1-linux.tgz
ENV ANDROID_HOME="/android-sdk-linux" ENV ANDROID_HOME="/root/android-sdk-linux"
ENV PATH="${PATH}:${ANDROID_HOME}/tools" ENV PATH="${PATH}:${ANDROID_HOME}/tools"
#===================================================== #=====================================================
@ -28,26 +48,33 @@ ENV PATH="${PATH}:${ANDROID_HOME}/tools"
RUN echo y | android update sdk --no-ui --filter 2,3 RUN echo y | android update sdk --no-ui --filter 2,3
ENV PATH="${PATH}:${ANDROID_HOME}/platform-tools" ENV PATH="${PATH}:${ANDROID_HOME}/platform-tools"
ENV PATH="${PATH}:${ANDROID_HOME}/build-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
#================================================== #====================================
# Fix issue regarding 64bit while running emulator # Install latest nodejs, npm, appium
#================================================== #====================================
RUN dpkg --add-architecture i386 RUN apt-get install curl -y
RUN apt-get update RUN curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
RUN apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 -y RUN apt-get install nodejs -y
ENV ANDROID_EMULATOR_FORCE_32BIT=true
RUN adb start-server
#============================================
# Install nodejs, npm, appium, appium-doctor
#============================================
RUN apt-get install npm nodejs-legacy -y
ENV APPIUM_VERSION 1.6.3 ENV APPIUM_VERSION 1.6.3
RUN npm install -g appium@$APPIUM_VERSION RUN npm install -g appium@$APPIUM_VERSION
#======================
# noVNC Configurations
#======================
ENV DISPLAY=:0 \
SCREEN=0 \
SCREEN_WIDTH=1600 \
SCREEN_HEIGHT=900 \
SCREEN_DEPTH=16 \
LOCAL_PORT=5900 \
TARGET_PORT=6080 \
TIMEOUT=1
RUN ln -s noVNC/vnc_auto.html noVNC/index.html
#=================== #===================
# Run docker-appium # Run docker-appium
#=================== #===================
COPY service /service COPY service /root/service
WORKDIR /service CMD python -m service.start
CMD python start.py

View file

@ -9,18 +9,27 @@ logger = logging.getLogger('android_appium')
def run(): def run():
""" """
Run Android emulator and Appium server. Start noVNC, installation of needed android SDK packages and Appium server.
""" """
android_version = os.getenv('ANDROID_VERSION', '4.2.2') android_version = os.getenv('ANDROID_VERSION', '4.2.2')
create_android_emulator(android_version) os.environ['emulator_name'] = 'emulator_{version}'.format(version=android_version)
emulator_name = 'emulator_{version}'.format(version=android_version) # Start Xvfb
subprocess.check_call('Xvfb ${DISPLAY} -screen ${SCREEN} ${SCREEN_WIDTH}x${SCREEN_HEIGHT}x${SCREEN_DEPTH} & '
'sleep ${TIMEOUT}', shell=True)
logger.info('android emulator name: {name} '.format(name=emulator_name)) # Start noVNC, installation of packages and appium
# TODO: check android emulator is ready to use vnc_cmd = 'openbox-session & x11vnc -display ${DISPLAY} -nopw -ncache 10 -forever & ' \
cmd_run = 'emulator -avd {name} -no-audio -no-window & appium'.format(name=emulator_name) './noVNC/utils/launch.sh --vnc localhost:${LOCAL_PORT} --listen ${TARGET_PORT}'
subprocess.check_call(cmd_run, shell=True) android_cmd = get_android_bash_commands(android_version)
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)
else:
logger.warning('There is no android packages installed!')
cmd = '({vnc}) & (xterm -e \"appium\")'.format(vnc=vnc_cmd)
subprocess.check_call(cmd, shell=True)
def get_available_sdk_packages(): def get_available_sdk_packages():
@ -30,12 +39,10 @@ def get_available_sdk_packages():
:return: List of available packages. :return: List of available packages.
:rtype: bytearray :rtype: bytearray
""" """
logger.info('List of Android SDK: ')
cmd = ['android', 'list', 'sdk'] cmd = ['android', 'list', 'sdk']
output_str = subprocess.check_output(cmd) output_str = subprocess.check_output(cmd)
logger.info('List of Android SDK: ')
logger.info(output_str) logger.info(output_str)
return [output.strip() for output in output_str.split('\n')] if output_str else None return [output.strip() for output in output_str.split('\n')] if output_str else None
@ -54,17 +61,20 @@ def get_item_position(keyword, items):
return pos return pos
def create_android_emulator(android_version): def get_android_bash_commands(android_version):
""" """
Create android emulator based on given android version. Get bash commands to install given android version and to create android emulator.
It include installation of sdk package and its armeabi v7a.
To see list of available targets: android list targets To see list of available targets: android list targets
To see list to avd: android list avd To see list to avd: android list avd
:param android_version: android version :param android_version: android version
:type android_version: str :type android_version: str
:return: bash commands
:rtype: bytearray
""" """
bash_command = None
try: try:
packages = get_available_sdk_packages() packages = get_available_sdk_packages()
@ -79,31 +89,29 @@ def create_android_emulator(android_version):
logger.info( logger.info(
'Package number: {number}, API version: {version}'.format(number=package_number, version=api_version)) 'Package number: {number}, API version: {version}'.format(number=package_number, version=api_version))
# Install SDK package commands = []
logger.info('Installing SDK package...') # Command to install SDK package
cmd_sdk = 'echo y | android update sdk --no-ui --filter {number}'.format(number=package_number) commands.append('echo y | android update sdk --no-ui --filter {number}'.format(number=package_number))
subprocess.check_call(cmd_sdk, shell=True)
logger.info('Installation completed')
# Install armeabi v7a # Command to install armeabi v7a
logger.info('Installing its armeabi...') commands.append('echo y | android update sdk --no-ui -a --filter sys-img-armeabi-v7a-android-{api}'.format(
cmd_arm = 'echo y | android update sdk --no-ui -a --filter sys-img-armeabi-v7a-android-{api}'.format( api=api_version))
api=api_version)
subprocess.check_call(cmd_arm, shell=True)
logger.info('Installation completed')
# Create android emulator # Command to create android emulator
logger.info('Creating android emulator...') commands.append(
cmd_emu = 'echo no | android create avd -f -n emulator_{version} -t android-{api} --abi armeabi-v7a'.format( 'echo no | android create avd -f -n emulator_{version} -t android-{api} --abi armeabi-v7a'.format(
version=android_version, api=api_version) version=android_version, api=api_version))
subprocess.check_call(cmd_emu, shell=True)
logger.info('Android emulator is created') # Join all commands in one str for xterm
bash_command = ' && '.join(commands)
else: else:
raise RuntimeError('Packages is empty!') raise RuntimeError('Packages is empty!')
except IndexError as i_err: except IndexError as i_err:
logger.error(i_err) logger.error(i_err)
return bash_command
if __name__ == '__main__': if __name__ == '__main__':
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)

View file

@ -9,11 +9,22 @@ from service import start
class TestService(TestCase): class TestService(TestCase):
"""Unit test class to test method run.""" """Unit test class to test method run."""
@mock.patch('service.start.create_android_emulator') @mock.patch('service.start.get_android_bash_commands')
@mock.patch('subprocess.check_call') @mock.patch('subprocess.check_call')
def test_service(self, mocked_creation, mocked_subprocess): def test_service(self, mocked_bash_cmd, mocked_subprocess):
self.assertFalse(mocked_creation.called) self.assertFalse(mocked_bash_cmd.called)
self.assertFalse(mocked_subprocess.called) self.assertFalse(mocked_subprocess.called)
start.run() start.run()
self.assertTrue(mocked_creation.called) self.assertTrue(mocked_bash_cmd.called)
self.assertTrue(mocked_subprocess.called) self.assertTrue(mocked_subprocess.called)
@mock.patch('service.start.get_android_bash_commands')
@mock.patch('subprocess.check_call')
@mock.patch('service.start.logger.warning')
def test_empty_android_cmd(self, mocked_bash_cmd, mocked_subprocess, mocked_logger_warning):
mocked_bash_cmd.return_value = None
self.assertFalse(mocked_subprocess.called)
self.assertFalse(mocked_logger_warning.called)
start.run()
self.assertTrue(mocked_subprocess.called)
self.assertTrue(mocked_logger_warning.called)

View file

@ -8,27 +8,28 @@ from service import start
@mock.patch('service.start.get_available_sdk_packages') @mock.patch('service.start.get_available_sdk_packages')
class TestRunService(TestCase): class TestRunService(TestCase):
"""Unit test class to test method create_android_emulator.""" """Unit test class to test method get_android_bash_commands."""
def test_create_emulator(self, mocked_packages): def test_create_emulator(self, mocked_packages):
mocked_packages.return_value = ['9- SDK Platform Android 4.4.2, API 19, revision 4', 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', '10- SDK Platform Android 4.3.1, API 18, revision 3',
'11- SDK Platform Android 4.2.2, API 17, revision 3'] '11- SDK Platform Android 4.2.2, API 17, revision 3']
with mock.patch('subprocess.check_call') as mocked_subprocess:
self.assertFalse(mocked_subprocess.called)
android_version = '4.2.2' android_version = '4.2.2'
start.create_android_emulator(android_version) cmd = start.get_android_bash_commands(android_version)
self.assertTrue(mocked_subprocess.called) self.assertIsNotNone(cmd)
self.assertTrue('android update sdk' in cmd)
self.assertTrue('android create avd' in cmd)
def test_empty_packages(self, mocked_packages): def test_empty_packages(self, mocked_packages):
mocked_packages.return_value = None mocked_packages.return_value = None
with self.assertRaises(RuntimeError): with self.assertRaises(RuntimeError):
start.create_android_emulator('4.2.2') start.get_android_bash_commands('4.2.2')
def test_index_error(self, mocked_packages): def test_index_error(self, mocked_packages):
mocked_packages.return_value = ['9 SDK Platform Android 4.4.2, API 19, revision 4', 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', '10 SDK Platform Android 4.3.1, API 18, revision 3',
'11 SDK Platform Android 4.2.2, API 17, revision 3'] '11 SDK Platform Android 4.2.2, API 17, revision 3']
android_version = '4.2.2' android_version = '4.2.2'
start.create_android_emulator(android_version) start.get_android_bash_commands(android_version)
self.assertRaises(IndexError) self.assertRaises(IndexError)