Enable preinstallation android packages

This commit is contained in:
butomo1989
2017-03-24 16:49:07 +01:00
parent ef3ead7067
commit 4fdf66f89f
27 changed files with 466 additions and 500 deletions
-1
View File
@@ -1,7 +1,6 @@
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')
-126
View File
@@ -1,126 +0,0 @@
import logging
import os
import subprocess
from src import ANDROID_PATH
logger = logging.getLogger('android')
EMULATOR = 'emulator'
TYPE_ARMEABI = 'armeabi'
TYPE_X86 = 'x86'
TYPE_X86_64 = 'x86_64'
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):
"""
Get api level of android version.
:param android_version: android version
:type android_version: str
:return: api level
:rtype: int
"""
api_level = None
try:
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)
return api_level
def install_package(emulator_file, api_level, sys_img):
"""
Install sdk package.
:param emulator_file: emulator file that need to be link
:type emulator_file: str
:param api_level: api level
:type api_level: str
:param sys_img: system image of emulator
: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')
os.symlink(emu_file, emu_target)
# Install package based on given android version
cmd = 'echo y | android update sdk --no-ui -a -t android-{api},sys-img-{sys_img}-android-{api}'.format(
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)
def create_avd(device, avd_name, api_level):
"""
Create android virtual device.
:param device: name of device
:type device: str
:param avd_name: desire name
:type avd_name: str
:param api_level: api level
:type api_level: str
"""
# 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:
# 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')
logger.info('Skin destination path: {dst}'.format(dst=skin_dst_path))
for s in os.listdir(skin_rsc_path):
os.symlink(os.path.join(skin_rsc_path, s), os.path.join(skin_dst_path, s))
# Hardware and its skin
device_name_bash = device.replace(' ', '\ ')
skin_name = device.replace(' ', '_').lower()
logger.info('device name in bash: {db}, skin name: {skin}'.format(db=device_name_bash, skin=skin_name))
# For custom hardware profile
profile_dst_path = os.path.join(ROOT, '.android', 'devices.xml')
if 'samsung' in device.lower():
# profile file name = skin name
profile_src_path = os.path.join(ROOT, 'devices', 'profiles', '{profile}.xml'.format(profile=skin_name))
logger.info('Hardware profile resource path: {rsc}'.format(rsc=profile_src_path))
logger.info('Hardware profile destination path: {dst}'.format(dst=profile_dst_path))
os.symlink(profile_src_path, profile_dst_path)
# append command
cmd += ' -d {device} -s {skin}'.format(device=device_name_bash, skin=skin_name)
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)
+182
View File
@@ -0,0 +1,182 @@
import json
import logging
import os
import subprocess
from src import CONFIG_FILE, ROOT
from src import log
log.init()
logger = logging.getLogger('app')
def get_or_raise(env):
"""
Check if needed environment variables are given.
:param env: key
:type env: str
:return: value
:rtype: str
"""
env_value = os.getenv(env)
if not env_value:
raise RuntimeError('The environment variable {0:s} is missing.'
'Please check docker image or Dockerfile!'.format(env))
return env_value
def str_to_bool(str):
"""
Convert string to boolean.
:param str: given string
:type str: str
:return: converted string
:rtype: bool
"""
try:
return str.lower() in ('yes', 'true', 't', '1')
except AttributeError as err:
logger.error(err)
ANDROID_HOME = get_or_raise('ANDROID_HOME')
ANDROID_VERSION = get_or_raise('ANDROID_VERSION')
API_LEVEL = get_or_raise('API_LEVEL')
PROCESSOR = get_or_raise('PROCESSOR')
SYS_IMG = get_or_raise('SYS_IMG')
logger.info('Android version: {version} \n'
'API level: {level} \n'
'Processor: {processor} \n'
'System image: {img}'.format(version=ANDROID_VERSION, level=API_LEVEL, processor=PROCESSOR,
img=SYS_IMG))
def prepare_avd(device, avd_name):
"""
Create and run android virtual device.
:param device: Device name
:type device: str
:param avd_name: Name of android virtual device / emulator
:type avd_name: str
"""
cmd = 'echo no | android create avd -f -n {name} -t android-{api} -b {sys_img}'.format(
name=avd_name, api=API_LEVEL, sys_img=SYS_IMG)
# Link emulator skins
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_HOME, '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):
os.symlink(os.path.join(skin_rsc_path, s), os.path.join(skin_dst_path, s))
# Hardware and its skin
device_name_bash = device.replace(' ', '\ ')
skin_name = device.replace(' ', '_').lower()
logger.info('Device name in bash: {db}, Skin name: {skin}'.format(db=device_name_bash, skin=skin_name))
# For custom hardware profile
profile_dst_path = os.path.join(ROOT, '.android', 'devices.xml')
if 'samsung' in device.lower():
# profile file name = skin name
profile_src_path = os.path.join(ROOT, 'devices', 'profiles', '{profile}.xml'.format(profile=skin_name))
logger.info('Hardware profile resource path: {rsc}'.format(rsc=profile_src_path))
logger.info('Hardware profile destination path: {dst}'.format(dst=profile_dst_path))
os.symlink(profile_src_path, profile_dst_path)
# Append command
cmd += ' -d {device} -s {skin}'.format(device=device_name_bash, skin=skin_name)
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)
def appium_run(avd_name):
"""
Run appium server.
:param avd_name: Name of android virtual device / emulator
:type avd_name: str
"""
cmd = 'appium'
grid_connect = str_to_bool(str(os.getenv('CONNECT_TO_GRID', False)))
logger.info('Connect to selenium grid? {connect}'.format(connect=grid_connect))
if grid_connect:
try:
appium_host = os.getenv('APPIUM_HOST', '127.0.0.1')
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(avd_name, 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 = 'Appium Server'
subprocess.check_call('xterm -T "{titel}" -n "{titel}" -e \"{cmd}\"'.format(titel=titel, cmd=cmd), shell=True)
def create_node_config(avd_name, appium_host, appium_port, selenium_host, selenium_port):
"""
Create custom node config file in json format to be able to connect with selenium server.
:param avd_name: Name of android virtual device / emulator
:type avd_name: str
:param appium_host: Host where appium server is running
:type appium_host: str
:param appium_port: Port number where where appium server is running
:type appium_port: int
:param selenium_host: Host where selenium server is running
:type selenium_host: str
:param selenium_port: Port number where selenium server is running
:type selenium_port: int
"""
config = {
'capabilities': [
{
'platform': 'Android',
'platformName': 'Android',
'version': ANDROID_VERSION,
'browserName': avd_name,
'maxInstances': 1,
}
],
'configuration': {
'cleanUpCycle': 2000,
'timeout': 30000,
'proxy': 'org.openqa.grid.selenium.proxy.DefaultRemoteProxy',
'url': 'http://{host}:{port}/wd/hub'.format(host=appium_host, port=appium_port),
'host': appium_host,
'port': appium_port,
'maxSession': 6,
'register': True,
'registerCycle': 5000,
'hubHost': selenium_host,
'hubPort': selenium_port
}
}
logger.info('Appium node config: {config}'.format(config=config))
with open(CONFIG_FILE, 'w') as cf:
cf.write(json.dumps(config))
def run():
"""Run app."""
device = os.getenv('DEVICE', 'Nexus 5')
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))
prepare_avd(device, avd_name)
appium = str_to_bool(str(os.getenv('APPIUM', True)))
if appium:
appium_run(avd_name)
if __name__ == '__main__':
run()
-84
View File
@@ -1,84 +0,0 @@
import json
import logging
import os
import subprocess
logger = logging.getLogger('appium')
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 avd_name: name of device
:type avd_name: str
:param android_version: android version
:type android_version: str
"""
cmd = 'appium'
if connect_to_grid:
from src import CONFIG_FILE
try:
appium_host = os.getenv('APPIUM_HOST', '127.0.0.1')
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, 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=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,
selenium_host, selenium_port):
"""
Create custom node config file in json format to be able to connect with selenium server.
:param config_file: config file
:type config_file: str
:param emulator_name: emulator name
:type emulator_name: str
:param android_version: android version of android emulator
:type android_version: str
:param appium_host: host where appium server is running
:type appium_host: str
:param appium_port: port number where where appium server is running
:type appium_port: int
:param selenium_host: host where selenium server is running
:type selenium_host: str
:param selenium_port: port number where selenium server is running
:type selenium_port: int
"""
config = {
'capabilities': [
{
'platform': 'Android',
'platformName': 'Android',
'version': android_version,
'browserName': emulator_name,
'maxInstances': 1,
}
],
'configuration': {
'cleanUpCycle': 2000,
'timeout': 30000,
'proxy': 'org.openqa.grid.selenium.proxy.DefaultRemoteProxy',
'url': 'http://{host}:{port}/wd/hub'.format(host=appium_host, port=appium_port),
'host': appium_host,
'port': appium_port,
'maxSession': 6,
'register': True,
'registerCycle': 5000,
'hubHost': selenium_host,
'hubPort': selenium_port
}
}
logger.info('appium node config: {config}'.format(config=config))
with open(config_file, 'w') as cf:
cf.write(json.dumps(config))
+3 -15
View File
@@ -1,5 +1,5 @@
[loggers]
keys=root, android, appium, service
keys=root, app
[handlers]
keys=console
@@ -11,23 +11,11 @@ keys=formatter
level=INFO
handlers=console
[logger_android]
[logger_app]
level=INFO
handlers=console
propagate=0
qualname=android
[logger_appium]
level=INFO
handlers=console
propagate=0
qualname=appium
[logger_service]
level=INFO
handlers=console
propagate=0
qualname=service
qualname=app
[handler_console]
class=StreamHandler
-69
View File
@@ -1,69 +0,0 @@
import logging
import os
from src import android, appium, log
logger = logging.getLogger('service')
def start():
"""
Installation of needed sdk package, creation of android emulator and execution of appium server.
"""
# Device name
device = os.getenv('DEVICE', 'Nexus 5')
# Android version
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))
# Install android sdk package
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.get_api_level('5.0'):
sys_img = android.TYPE_X86
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(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(device, avd_name, api_level)
# Run appium server
appium.run(connect_to_grid, avd_name, android_version)
def str_to_bool(str):
"""
Convert string to boolean.
:param str: given string
:type str: str
:return: converted string
:rtype: bool
"""
return str.lower() in ('yes', 'true', 't', '1')
if __name__ == '__main__':
log.init()
start()
+49
View File
@@ -0,0 +1,49 @@
"""Unit test to test app."""
import os
from unittest import TestCase
import mock
from src import app
class TestApp(TestCase):
"""Unit test class to test other methods in the app."""
def test_valid_env(self):
key = 'ENV_1'
os.environ[key] = 'test'
app.get_or_raise(key)
del os.environ[key]
def test_invalid_env(self):
with self.assertRaises(RuntimeError):
app.get_or_raise('ENV_2')
def test_valid_bool(self):
self.assertEqual(app.str_to_bool('True'), True)
self.assertEqual(app.str_to_bool('t'), True)
self.assertEqual(app.str_to_bool('1'), True)
self.assertEqual(app.str_to_bool('YES'), True)
def test_invalid_bool(self):
self.assertEqual(app.str_to_bool(''), False)
self.assertEqual(app.str_to_bool('test'), False)
def test_invalid_format(self):
self.assertEqual(app.str_to_bool(True), None)
@mock.patch('src.app.prepare_avd')
def test_run_with_appium(self, mocked_avd):
with mock.patch('src.app.appium_run') as mocked_appium:
app.run()
self.assertTrue(mocked_avd.called)
self.assertTrue(mocked_appium.called)
@mock.patch('src.app.prepare_avd')
def test_run_withhout_appium(self, mocked_avd):
with mock.patch('src.app.appium_run') as mocked_appium:
os.environ['APPIUM'] = str(False)
app.run()
self.assertTrue(mocked_avd.called)
self.assertFalse(mocked_appium.called)
View File
-20
View File
@@ -1,20 +0,0 @@
"""Unit test for android.py."""
from unittest import TestCase
from src import android
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):
api_level = android.get_api_level('4.2')
self.assertEqual(api_level, 19)
def test_wrong_type(self):
api_level = android.get_api_level(4)
self.assertRaises(TypeError)
self.assertEqual(api_level, None)
-24
View File
@@ -1,24 +0,0 @@
"""Unit test for android.py."""
from unittest import TestCase
import mock
from src import android
class TestInstallPackage(TestCase):
"""Unit test class to test method install_package."""
def setUp(self):
self.emulator_file = 'emulator64-arm'
self.api_level = 21
self.sys_img = 'armeabi-v7a'
@mock.patch('os.symlink')
@mock.patch('subprocess.check_call')
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.emulator_file, self.api_level, self.sys_img)
self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_suprocess.called)
View File
-16
View File
@@ -1,16 +0,0 @@
"""Unit test for appium.py."""
import os
from unittest import TestCase
from src import CONFIG_FILE, appium
class TestAppiumConfig(TestCase):
"""Unit test class to test method create_node_config."""
def test_config_creation(self):
self.assertFalse(os.path.exists(CONFIG_FILE))
appium.create_node_config(CONFIG_FILE, 'emulator_name', '4.2.2', '127.0.0.1', 4723, '127.0.0.1', 4444)
self.assertTrue(os.path.exists(CONFIG_FILE))
os.remove(CONFIG_FILE)
-46
View File
@@ -1,46 +0,0 @@
"""Unit test for appium.py."""
import os
from unittest import TestCase
import mock
from src import appium
@mock.patch('subprocess.check_call')
class TestAppiumConfig(TestCase):
"""Unit test class to test method run."""
def setUp(self):
self.emulator_name = 'test'
self.android_version = '4.2.2'
def test_without_selenium_grid(self, mocked_subprocess):
with mock.patch('src.appium.create_node_config') as mocked_config:
self.assertFalse(mocked_config.called)
self.assertFalse(mocked_subprocess.called)
appium.run(False, self.emulator_name, self.android_version)
self.assertFalse(mocked_config.called)
self.assertTrue(mocked_subprocess.called)
def test_with_selenium_grid(self, mocked_subprocess):
with mock.patch('src.appium.create_node_config') as mocked_config:
self.assertFalse(mocked_config.called)
self.assertFalse(mocked_subprocess.called)
appium.run(True, self.emulator_name, self.android_version)
self.assertTrue(mocked_config.called)
self.assertTrue(mocked_subprocess.called)
def test_invalid_integer(self, mocked_subprocess):
os.environ['APPIUM_PORT'] = 'test'
with mock.patch('src.appium.create_node_config') as mocked_config:
self.assertFalse(mocked_config.called)
self.assertFalse(mocked_subprocess.called)
appium.run(True, self.emulator_name, self.android_version)
self.assertFalse(mocked_config.called)
self.assertTrue(mocked_subprocess.called)
self.assertRaises(ValueError)
def tearDown(self):
if os.getenv('APPIUM_PORT'):
del os.environ['APPIUM_PORT']
+54
View File
@@ -0,0 +1,54 @@
"""Unit test to test appium service."""
import os
from unittest import TestCase
import mock
from src import app
class TestAppium(TestCase):
"""Unit test class to test appium methods."""
def setUp(self):
os.environ['CONNECT_TO_GRID'] = str(True)
self.avd_name = 'test_avd'
@mock.patch('subprocess.check_call')
def test_without_selenium_grid(self, mocked_subprocess):
os.environ['CONNECT_TO_GRID'] = str(False)
self.assertFalse(mocked_subprocess.called)
app.appium_run(self.avd_name)
self.assertTrue(mocked_subprocess.called)
@mock.patch('subprocess.check_call')
def test_with_selenium_grid(self, mocked_subprocess):
with mock.patch('src.app.create_node_config') as mocked_config:
self.assertFalse(mocked_config.called)
self.assertFalse(mocked_subprocess.called)
app.appium_run(self.avd_name)
self.assertTrue(mocked_config.called)
self.assertTrue(mocked_subprocess.called)
@mock.patch('subprocess.check_call')
def test_invalid_integer(self, mocked_subprocess):
os.environ['APPIUM_PORT'] = 'test'
with mock.patch('src.app.create_node_config') as mocked_config:
self.assertFalse(mocked_config.called)
self.assertFalse(mocked_subprocess.called)
app.appium_run(self.avd_name)
self.assertFalse(mocked_config.called)
self.assertTrue(mocked_subprocess.called)
self.assertRaises(ValueError)
def test_config_creation(self):
from src import CONFIG_FILE
self.assertFalse(os.path.exists(CONFIG_FILE))
app.create_node_config('test', '127.0.0.1', 4723, '127.0.0.1', 4444)
self.assertTrue(os.path.exists(CONFIG_FILE))
os.remove(CONFIG_FILE)
def tearDown(self):
del os.environ['CONNECT_TO_GRID']
if os.getenv('APPIUM_PORT'):
del os.environ['APPIUM_PORT']
@@ -1,9 +1,10 @@
"""Unit test for android.py."""
"""Unit test for android virtual device creation.py."""
import os
from unittest import TestCase
import mock
from src import android
from src import app
@mock.patch('subprocess.check_call')
@@ -13,15 +14,14 @@ class TestAvd(TestCase):
def setUp(self):
self.avd_name = 'test_avd'
self.api_level = 21
def test_nexus_avd(self, mocked_suprocess, mocked_sys_link):
def test_nexus_avd_as_default(self, mocked_suprocess, mocked_sys_link):
with mock.patch('os.listdir') as mocked_list_dir:
mocked_list_dir.return_value = ['file1', 'file2']
self.assertFalse(mocked_list_dir.called)
self.assertFalse(mocked_sys_link.called)
self.assertFalse(mocked_suprocess.called)
android.create_avd('Nexus 5', self.avd_name, self.api_level)
app.prepare_avd('Nexus 5', self.avd_name)
self.assertTrue(mocked_list_dir.called)
self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_suprocess.called)
@@ -32,16 +32,11 @@ class TestAvd(TestCase):
self.assertFalse(mocked_list_dir.called)
self.assertFalse(mocked_sys_link.called)
self.assertFalse(mocked_suprocess.called)
android.create_avd('Samsung Galaxy S6', self.avd_name, self.api_level)
app.prepare_avd('Samsung Galaxy S6', self.avd_name)
self.assertTrue(mocked_list_dir.called)
self.assertTrue(mocked_sys_link.called)
self.assertTrue(mocked_suprocess.called)
def test_default_avd(self, mocked_suprocess, mocked_sys_link):
with mock.patch('os.listdir') as mocked_list_dir:
mocked_list_dir.return_value = ['file1', 'file2']
self.assertFalse(mocked_list_dir.called)
self.assertFalse(mocked_sys_link.called)
self.assertFalse(mocked_suprocess.called)
android.create_avd('emulator', self.avd_name, self.api_level)
self.assertFalse(mocked_list_dir.called)
def tearDown(self):
if os.getenv('DEVICE'):
del os.environ['DEVICE']