Refactored

This commit is contained in:
butomo1989 2017-03-21 13:33:46 +01:00
parent 26b99bd32b
commit f4e16a3cf2
10 changed files with 76 additions and 176 deletions

View file

@ -46,8 +46,8 @@ ENV PATH="${PATH}:${JAVA_HOME}/bin"
#=====================
RUN apt-get install wget unzip libqt5webkit5 -y
RUN wget https://dl.google.com/android/repository/tools_r25.2.3-linux.zip
RUN unzip tools_r25.2.3-linux.zip && rm tools_r25.2.3-linux.zip
RUN wget https://dl.google.com/android/repository/tools_r25.2.3-linux.zip && \
unzip tools_r25.2.3-linux.zip && rm tools_r25.2.3-linux.zip
ENV ANDROID_HOME="/root"
ENV PATH="${PATH}:${ANDROID_HOME}/tools"
@ -55,9 +55,8 @@ ENV PATH="${PATH}:${ANDROID_HOME}/tools"
# Install Platform-tools, Build-tools
# To see list of available packages: android list sdk
#=====================================================
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 echo y | android update sdk --no-ui --filter platform-tools,build-tools-25.0.2
ENV PATH="${PATH}:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/build-tools"
RUN mv ${ANDROID_HOME}/tools/emulator ${ANDROID_HOME}/tools/emulator.backup
#====================================

View file

@ -1,6 +1,7 @@
import os
ROOT = '/root'
ANDROID_PATH = os.getenv('ANDROID_HOME', '/root')
WORKDIR = os.path.dirname(__file__)
CONFIG_FILE = os.path.join(WORKDIR, 'nodeconfig.json')
LOGGING_FILE = os.path.join(WORKDIR, 'logging.conf')

View file

@ -1,44 +1,37 @@
import logging
import os
import re
import subprocess
logging.basicConfig()
from src import ANDROID_PATH
logger = logging.getLogger('android')
# not using enum because need to install pip that will make docker image size bigger
EMULATOR = 'emulator'
TYPE_ARMEABI = 'armeabi'
TYPE_X86 = 'x86'
TYPE_X86_64 = 'x86_64'
API_LEVEL_ANDROID_5 = 21
def get_available_sdk_packages():
"""
Get list of available sdk packages.
:return: List of available packages.
:rtype: bytearray
"""
logger.info('List of Android SDK: ')
output_str = subprocess.check_output('android list sdk'.split())
logger.info(output_str)
return [output.strip() for output in output_str.split('\n')] if output_str else None
def get_item_position(keyword, items):
"""
Get position of item in array by given keyword.
:return: item position
:rtype: int
"""
pos = 0
for p, v in enumerate(items):
if keyword in v:
pos = p # Get the last item that match with keyword
return pos
API_LEVELS = {
'2.1': 7,
'2.2': 8,
'2.3.1': 9,
'2.3.3': 1,
'3.0': 11,
'3.1': 12,
'3.2': 13,
'4.0': 14,
'4.0.3': 15,
'4.1.2': 16,
'4.2.2': 17,
'4.3.1': 18,
'4.4.2': 19,
'4.4W.2': 20,
'5.0.1': 21,
'5.1.1': 22,
'6.0': 23,
'7.0': 24,
'7.1.1': 25
}
def get_api_level(android_version):
@ -47,38 +40,25 @@ def get_api_level(android_version):
:param android_version: android version
:type android_version: str
:return: api version
:rtype: str
:return: api level
:rtype: int
"""
api_version = None
api_level = None
try:
packages = get_available_sdk_packages()
for key in sorted(API_LEVELS):
if android_version in key:
api_level = API_LEVELS.get(key)
except TypeError as t_err:
logger.error(t_err)
if packages:
item_pos = get_item_position(android_version, packages)
logger.info('Package in position: {pos}'.format(pos=item_pos))
item = packages[item_pos]
logger.info('Item: {item}'.format(item=item))
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))
else:
raise RuntimeError('List of packages is empty!')
except IndexError as i_err:
logger.error(i_err)
return api_version
return api_level
def install_package(android_path, emulator_file, api_level, sys_img):
def install_package(emulator_file, api_level, sys_img):
"""
Install sdk package.
:param android_path: location where android SDK is installed
:type android_path: str
:param emulator_file: emulator file that need to be link
:type emulator_file: str
:param api_level: api level
@ -87,8 +67,8 @@ def install_package(android_path, emulator_file, api_level, sys_img):
:type sys_img: str
"""
# Link emulator shortcut
emu_file = os.path.join(android_path, 'tools', emulator_file)
emu_target = os.path.join(android_path, 'tools', 'emulator')
emu_file = os.path.join(ANDROID_PATH, 'tools', emulator_file)
emu_target = os.path.join(ANDROID_PATH, 'tools', 'emulator')
os.symlink(emu_file, emu_target)
# Install package based on given android version
@ -96,16 +76,13 @@ def install_package(android_path, emulator_file, api_level, sys_img):
api=api_level, sys_img=sys_img)
logger.info('SDK package installation command: {install}'.format(install=cmd))
titel = 'SDK package installation process'
subprocess.check_call('xterm -T "{titel}" -n "{titel}" -e \"{cmd}\"'.format(
titel=titel, cmd=cmd), shell=True)
subprocess.check_call('xterm -T "{titel}" -n "{titel}" -e \"{cmd}\"'.format(titel=titel, cmd=cmd), shell=True)
def create_avd(android_path, device, avd_name, api_level):
def create_avd(device, 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 avd_name: desire name
@ -115,13 +92,13 @@ def create_avd(android_path, device, 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 != 'emulator':
if device != EMULATOR:
# Link emulator skins
from src import ROOT
skin_rsc_path = os.path.join(ROOT, 'devices', 'skins')
logger.info('Skin ressource path: {rsc}'.format(rsc=skin_rsc_path))
skin_dst_path = os.path.join(android_path, 'platforms', 'android-{api}'.format(api=api_level), 'skins')
skin_dst_path = os.path.join(ANDROID_PATH, '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):
@ -146,5 +123,4 @@ def create_avd(android_path, device, avd_name, api_level):
logger.info('AVD creation command: {cmd}'.format(cmd=cmd))
titel = 'AVD creation process'
subprocess.check_call('xterm -T "{titel}" -n "{titel}" -e \"{cmd}\"'.format(
titel=titel, cmd=cmd), shell=True)
subprocess.check_call('xterm -T "{titel}" -n "{titel}" -e \"{cmd}\"'.format(titel=titel, cmd=cmd), shell=True)

View file

@ -6,14 +6,14 @@ import subprocess
logger = logging.getLogger('appium')
def run(connect_to_grid, emulator_name, android_version):
def run(connect_to_grid, avd_name, android_version):
"""
Run appium server.
:param connect_to_grid: option to connect with selenium grid
:type connect_to_grid: bool
:param emulator_name: name of emulator
:type emulator_name: str
:param avd_name: name of device
:type avd_name: str
:param android_version: android version
:type android_version: str
"""
@ -25,14 +25,13 @@ def run(connect_to_grid, emulator_name, android_version):
appium_port = int(os.getenv('APPIUM_PORT', 4723))
selenium_host = os.getenv('SELENIUM_HOST', '172.17.0.1')
selenium_port = int(os.getenv('SELENIUM_PORT', 4444))
create_node_config(CONFIG_FILE, emulator_name, android_version,
appium_host, appium_port, selenium_host, selenium_port)
create_node_config(CONFIG_FILE, avd_name, android_version, appium_host, appium_port,
selenium_host, selenium_port)
cmd += ' --nodeconfig {file}'.format(file=CONFIG_FILE)
except ValueError as v_err:
logger.error(v_err)
titel = 'avd name: {name}'.format(name=emulator_name)
subprocess.check_call('xterm -T "{titel}" -n "{titel}" -e \"{cmd}\"'.format(
titel=titel, cmd=cmd), shell=True)
titel = 'avd name: {name}'.format(name=avd_name)
subprocess.check_call('xterm -T "{titel}" -n "{titel}" -e \"{cmd}\"'.format(titel=titel, cmd=cmd), shell=True)
def create_node_config(config_file, emulator_name, android_version, appium_host, appium_port,

View file

@ -11,25 +11,20 @@ def start():
Installation of needed sdk package, creation of android emulator and execution of appium server.
"""
# Android SDK path
android_path = os.getenv('ANDROID_HOME', '/root')
logger.info('Android path: {path}'.format(path=android_path))
# Emulator informations
emu_type = os.getenv('EMULATOR_TYPE', android.TYPE_ARMEABI).lower()
emu_type = android.TYPE_ARMEABI if emu_type not in [android.TYPE_ARMEABI, android.TYPE_X86] else \
emu_type
logger.info('Emulator type: {type}'.format(type=emu_type))
emu_file = 'emulator64-x86' if emu_type == android.TYPE_X86 else 'emulator64-arm'
logger.info('Emulator file: {file}'.format(file=emu_file))
# Device name
device = os.getenv('DEVICE', 'Nexus 5')
# Android version
android_version = os.getenv('ANDROID_VERSION', '4.2.2')
android_version = os.getenv('ANDROID_VERSION', '5.0')
logger.info('Android version: {version}'.format(version=android_version))
# Emulator type
emu_type = os.getenv('EMULATOR_TYPE', android.TYPE_ARMEABI).lower()
emu_type = android.TYPE_ARMEABI if emu_type not in [android.TYPE_ARMEABI, android.TYPE_X86] else emu_type
logger.info('Emulator type: {type}'.format(type=emu_type))
emu_file = 'emulator64-x86' if emu_type == android.TYPE_X86 else 'emulator64-arm'
logger.info('Emulator file: {file}'.format(file=emu_file))
# Selenium grid connection
connect_to_grid = str_to_bool(str(os.getenv('CONNECT_TO_GRID', False)))
logger.info('Connect to selenium grid? {input}'.format(input=connect_to_grid))
@ -38,21 +33,21 @@ def start():
api_level = android.get_api_level(android_version)
# Bug: cannot use skin for system image x86 with android version < 5.0
if emu_type == android.TYPE_X86:
if int(api_level) < android.API_LEVEL_ANDROID_5:
if int(api_level) < android.get_api_level('5.0'):
sys_img = android.TYPE_X86
device = 'emulator'
device = android.EMULATOR
else:
sys_img = android.TYPE_X86_64
else:
sys_img = '{type}-v7a'.format(type=android.TYPE_ARMEABI)
logger.info('System image: {sys_img}'.format(sys_img=sys_img))
android.install_package(android_path, emu_file, api_level, sys_img)
android.install_package(emu_file, api_level, sys_img)
# Create android virtual device
logger.info('Device: {device}'.format(device=device))
avd_name = '{device}_{version}'.format(device=device.replace(' ', '_').lower(), version=android_version)
logger.info('AVD name: {avd}'.format(avd=avd_name))
android.create_avd(android_path, device, avd_name, api_level)
android.create_avd(device, avd_name, api_level)
# Run appium server
appium.run(connect_to_grid, avd_name, android_version)

View file

@ -1,33 +1,20 @@
"""Unit test for android.py."""
from unittest import TestCase
import mock
from src import android
@mock.patch('src.android.get_available_sdk_packages')
class TestApiLevel(TestCase):
"""Unit test class to test method get_api_level."""
def setUp(self):
self.android_version = '4.2.2'
def test_get_api_level(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']
api_level = android.get_api_level(self.android_version)
self.assertEqual(api_level, '17')
def test_get_api_level(self):
api_level = android.get_api_level('4.2')
self.assertEqual(api_level, 19)
def test_empty_packages(self, mocked_packages):
mocked_packages.return_value = None
with self.assertRaises(RuntimeError):
android.get_api_level(self.android_version)
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.get_api_level(self.android_version)
self.assertRaises(IndexError)
def test_wrong_type(self):
api_level = android.get_api_level(4)
self.assertRaises(TypeError)
self.assertEqual(api_level, None)

View file

@ -1,28 +0,0 @@
"""Unit test for android.py."""
from unittest import TestCase
import mock
from src import android
class TestAvailablePackages(TestCase):
"""Unit test class to test method get_available_sdk_packages."""
@mock.patch('subprocess.check_output')
def test_valid_output(self, mocked_output):
mocked_output.return_value = 'package 1 \n package 2'
output = android.get_available_sdk_packages()
self.assertEqual(['package 1', 'package 2'], output)
@mock.patch('subprocess.check_output')
def test_without_line_break(self, mocked_output):
mocked_output.return_value = 'package 1, package 2'
output = android.get_available_sdk_packages()
self.assertEqual(['package 1, package 2'], output)
@mock.patch('subprocess.check_output')
def test_empty_string(self, mocked_output):
mocked_output.return_value = None
output = android.get_available_sdk_packages()
self.assertEqual(None, output)

View file

@ -12,7 +12,6 @@ class TestAvd(TestCase):
"""Unit test class to test method create_avd."""
def setUp(self):
self.android_path = '/root'
self.avd_name = 'test_avd'
self.api_level = 21
@ -22,7 +21,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, 'Nexus 5', self.avd_name, self.api_level)
android.create_avd('Nexus 5', self.avd_name, self.api_level)
self.assertTrue(mocked_list_dir.called)
self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_suprocess.called)
@ -33,7 +32,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, 'Samsung Galaxy S6', self.avd_name, self.api_level)
android.create_avd('Samsung Galaxy S6', self.avd_name, self.api_level)
self.assertTrue(mocked_list_dir.called)
self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_suprocess.called)
@ -44,5 +43,5 @@ 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, 'emulator', self.avd_name, self.api_level)
android.create_avd('emulator', self.avd_name, self.api_level)
self.assertFalse(mocked_list_dir.called)

View file

@ -10,7 +10,6 @@ class TestInstallPackage(TestCase):
"""Unit test class to test method install_package."""
def setUp(self):
self.android_path = '/root'
self.emulator_file = 'emulator64-arm'
self.api_level = 21
self.sys_img = 'armeabi-v7a'
@ -20,6 +19,6 @@ class TestInstallPackage(TestCase):
def test_package_installation(self, mocked_sys_link, mocked_suprocess):
self.assertFalse(mocked_sys_link.called)
self.assertFalse(mocked_suprocess.called)
android.install_package(self.android_path, self.emulator_file, self.api_level, self.sys_img)
android.install_package(self.emulator_file, self.api_level, self.sys_img)
self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_suprocess.called)

View file

@ -1,27 +0,0 @@
"""Unit test for android.py."""
from unittest import TestCase
from src import android
class TestItemPosition(TestCase):
"""Unit test class to test method get_item_position."""
def setUp(self):
self.items = ['android 4.1', 'android 4.2.2', 'android 4.3', 'android 4.4', 'android 4.4.2']
def test_valid_params(self):
keyword = '4.2'
output = android.get_item_position(keyword, self.items)
self.assertEqual(4, output)
def test_invalid_keyword(self):
keyword = 'fake'
output = android.get_item_position(keyword, self.items)
self.assertEqual(0, output)
def test_empty_array(self):
items = []
keyword = '4.2'
output = android.get_item_position(keyword, items)
self.assertEqual(0, output)