support noVNC
This commit is contained in:
parent
08b0e65216
commit
7785e56a2a
71
Dockerfile
71
Dockerfile
|
@ -1,24 +1,44 @@
|
|||
FROM ubuntu:16.04
|
||||
FROM ubuntu:14.04
|
||||
|
||||
#=======================
|
||||
# General Configuration
|
||||
#=======================
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
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
|
||||
#==============
|
||||
RUN apt-get install openjdk-8-jdk -y
|
||||
ENV JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/jre"
|
||||
RUN apt-get install openjdk-7-jdk -y
|
||||
ENV JAVA_HOME="/usr/lib/jvm/java-7-openjdk-amd64/jre"
|
||||
ENV PATH="${PATH}:${JAVA_HOME}/bin"
|
||||
|
||||
#=====================
|
||||
# Install Android SDK
|
||||
#=====================
|
||||
RUN apt-get install wget -y
|
||||
RUN wget http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
|
||||
RUN tar -xvzf android-sdk_r24.4.1-linux.tgz
|
||||
ENV ANDROID_HOME="/android-sdk-linux"
|
||||
RUN tar -xvzf android-sdk_r24.4.1-linux.tgz && rm android-sdk_r24.4.1-linux.tgz
|
||||
ENV ANDROID_HOME="/root/android-sdk-linux"
|
||||
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
|
||||
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
|
||||
|
||||
#==================================================
|
||||
# Fix issue regarding 64bit while running emulator
|
||||
#==================================================
|
||||
RUN dpkg --add-architecture i386
|
||||
RUN apt-get update
|
||||
RUN apt-get install libc6:i386 libncurses5:i386 libstdc++6:i386 -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
|
||||
#====================================
|
||||
# Install latest nodejs, npm, appium
|
||||
#====================================
|
||||
RUN apt-get install curl -y
|
||||
RUN curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash -
|
||||
RUN apt-get install nodejs -y
|
||||
ENV APPIUM_VERSION 1.6.3
|
||||
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
|
||||
#===================
|
||||
COPY service /service
|
||||
WORKDIR /service
|
||||
CMD python start.py
|
||||
COPY service /root/service
|
||||
CMD python -m service.start
|
||||
|
|
|
@ -9,18 +9,27 @@ logger = logging.getLogger('android_appium')
|
|||
|
||||
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')
|
||||
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))
|
||||
# TODO: check android emulator is ready to use
|
||||
cmd_run = 'emulator -avd {name} -no-audio -no-window & appium'.format(name=emulator_name)
|
||||
subprocess.check_call(cmd_run, shell=True)
|
||||
# Start noVNC, installation of packages 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)
|
||||
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():
|
||||
|
@ -30,12 +39,10 @@ def get_available_sdk_packages():
|
|||
:return: List of available packages.
|
||||
:rtype: bytearray
|
||||
"""
|
||||
logger.info('List of Android SDK: ')
|
||||
cmd = ['android', 'list', 'sdk']
|
||||
|
||||
output_str = subprocess.check_output(cmd)
|
||||
logger.info('List of Android SDK: ')
|
||||
logger.info(output_str)
|
||||
|
||||
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
|
||||
|
||||
|
||||
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 to avd: android list avd
|
||||
|
||||
:param android_version: android version
|
||||
:type android_version: str
|
||||
:return: bash commands
|
||||
:rtype: bytearray
|
||||
"""
|
||||
bash_command = None
|
||||
|
||||
try:
|
||||
packages = get_available_sdk_packages()
|
||||
|
||||
|
@ -79,31 +89,29 @@ def create_android_emulator(android_version):
|
|||
logger.info(
|
||||
'Package number: {number}, API version: {version}'.format(number=package_number, version=api_version))
|
||||
|
||||
# Install SDK package
|
||||
logger.info('Installing SDK package...')
|
||||
cmd_sdk = 'echo y | android update sdk --no-ui --filter {number}'.format(number=package_number)
|
||||
subprocess.check_call(cmd_sdk, shell=True)
|
||||
logger.info('Installation completed')
|
||||
commands = []
|
||||
# Command to install SDK package
|
||||
commands.append('echo y | android update sdk --no-ui --filter {number}'.format(number=package_number))
|
||||
|
||||
# Install armeabi v7a
|
||||
logger.info('Installing its armeabi...')
|
||||
cmd_arm = 'echo y | android update sdk --no-ui -a --filter sys-img-armeabi-v7a-android-{api}'.format(
|
||||
api=api_version)
|
||||
subprocess.check_call(cmd_arm, shell=True)
|
||||
logger.info('Installation completed')
|
||||
# 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))
|
||||
|
||||
# Create android emulator
|
||||
logger.info('Creating android emulator...')
|
||||
cmd_emu = 'echo no | android create avd -f -n emulator_{version} -t android-{api} --abi armeabi-v7a'.format(
|
||||
version=android_version, api=api_version)
|
||||
subprocess.check_call(cmd_emu, shell=True)
|
||||
logger.info('Android emulator is created')
|
||||
# Command to create android emulator
|
||||
commands.append(
|
||||
'echo no | android create avd -f -n emulator_{version} -t android-{api} --abi armeabi-v7a'.format(
|
||||
version=android_version, api=api_version))
|
||||
|
||||
# Join all commands in one str for xterm
|
||||
bash_command = ' && '.join(commands)
|
||||
else:
|
||||
raise RuntimeError('Packages is empty!')
|
||||
|
||||
except IndexError as i_err:
|
||||
logger.error(i_err)
|
||||
|
||||
return bash_command
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logger.setLevel(logging.INFO)
|
||||
|
|
|
@ -9,11 +9,22 @@ from service import start
|
|||
class TestService(TestCase):
|
||||
"""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')
|
||||
def test_service(self, mocked_creation, mocked_subprocess):
|
||||
self.assertFalse(mocked_creation.called)
|
||||
def test_service(self, mocked_bash_cmd, mocked_subprocess):
|
||||
self.assertFalse(mocked_bash_cmd.called)
|
||||
self.assertFalse(mocked_subprocess.called)
|
||||
start.run()
|
||||
self.assertTrue(mocked_creation.called)
|
||||
self.assertTrue(mocked_bash_cmd.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)
|
||||
|
|
|
@ -8,27 +8,28 @@ from service import start
|
|||
|
||||
@mock.patch('service.start.get_available_sdk_packages')
|
||||
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):
|
||||
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']
|
||||
with mock.patch('subprocess.check_call') as mocked_subprocess:
|
||||
self.assertFalse(mocked_subprocess.called)
|
||||
android_version = '4.2.2'
|
||||
start.create_android_emulator(android_version)
|
||||
self.assertTrue(mocked_subprocess.called)
|
||||
|
||||
android_version = '4.2.2'
|
||||
cmd = start.get_android_bash_commands(android_version)
|
||||
self.assertIsNotNone(cmd)
|
||||
self.assertTrue('android update sdk' in cmd)
|
||||
self.assertTrue('android create avd' in cmd)
|
||||
|
||||
def test_empty_packages(self, mocked_packages):
|
||||
mocked_packages.return_value = None
|
||||
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):
|
||||
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.create_android_emulator(android_version)
|
||||
start.get_android_bash_commands(android_version)
|
||||
self.assertRaises(IndexError)
|
Loading…
Reference in a new issue