| """System image UI tests""" |
| |
| import unittest |
| import os |
| import time |
| import psutil |
| import shutil |
| import sys |
| import re |
| from subprocess import PIPE |
| |
| from emu_test.utils.emu_argparser import emu_args |
| from emu_test.utils.emu_testcase import EmuBaseTestCase, create_test_case_from_file |
| |
| class UiAutomatorBaseTestCase(EmuBaseTestCase): |
| def __init__(self, *args, **kwargs): |
| super(UiAutomatorBaseTestCase, self).__init__(*args, **kwargs) |
| self.avd_config = None |
| |
| @classmethod |
| def setUpClass(cls): |
| super(UiAutomatorBaseTestCase, cls).setUpClass() |
| |
| def tearDown(self): |
| self.m_logger.debug('First try - quit emulator by adb emu kill') |
| kill_proc = psutil.Popen(["adb", "emu", "kill"]) |
| # check emulator process is terminated |
| result = self.term_check(timeout=5) |
| if not result: |
| self.m_logger.debug('Second try - quit emulator by psutil') |
| self.kill_proc_by_name(["emulator", "qemu-system"]) |
| result = self.term_check(timeout=10) |
| self.m_logger.debug("term_check after psutil.kill - %s", result) |
| self.m_logger.info("Remove AVD inside of tear down") |
| # avd should be found $HOME/.android/avd/ |
| avd_dir = os.path.join(os.path.expanduser('~'), '.android', 'avd') |
| try: |
| if result and self.start_proc: |
| self.start_proc.wait() |
| time.sleep(1) |
| self.kill_proc_by_name(["crash-service", "adb"]) |
| os.remove(os.path.join(avd_dir, '%s.ini' % self.avd_config.name())) |
| shutil.rmtree(os.path.join(avd_dir, '%s.avd' % self.avd_config.name()), ignore_errors=True) |
| except Exception, e: |
| self.m_logger.error("Error in cleanup - %r", e) |
| pass |
| |
| def _save_gradle_test_report(self, test_method): |
| gradle_report_path = os.path.join(self.uitest_dir, 'app', 'build', 'reports', 'androidTests', 'connected', '') |
| if not os.path.exists(gradle_report_path): |
| self.m_logger.info('Failed to find gradle reports.') |
| return |
| dst_path = os.path.join(emu_args.session_dir, test_method + '_report') |
| if os.path.exists(dst_path): |
| shutil.rmtree(dst_path) |
| shutil.copytree(gradle_report_path, dst_path) |
| |
| def _save_adb_bug_report(self, test_method): |
| dst_path = os.path.join(emu_args.session_dir, test_method + '_bugreport.txt') |
| with open(dst_path, 'w') as f: |
| p = psutil.Popen(['adb', 'bugreport'], stdout=f, stderr=f) |
| p.communicate() |
| |
| def _pull_log_details(self, test_method): |
| dst_path = os.path.join(emu_args.session_dir, test_method + '_details') |
| p = psutil.Popen(['adb', 'pull', |
| '/sdcard/Logs', dst_path], |
| stdout=PIPE, stderr=PIPE) |
| (out, err) = p.communicate() |
| self.m_logger.info('adb_pull_stdout:\n' + out) |
| self.m_logger.info('adb_pull_stderr:\n' + err) |
| |
| def _launch_ui_test_with_avd_configs(self, avd): |
| test_args_prefix = '-Pandroid.testInstrumentationRunnerArguments' |
| test_package = test_args_prefix + '.package=com.android.devtools.systemimage.uitest.smoke' |
| test_api = test_args_prefix + '.api=' + avd.api |
| test_abi = test_args_prefix + '.abi=' + avd.abi |
| test_tag = test_args_prefix + '.tag=' + avd.tag |
| test_ori = test_args_prefix + '.origin=' + avd.ori |
| return psutil.Popen([self.gradle, 'cAT', test_package, test_api, test_abi, test_tag, test_ori], |
| cwd=self.uitest_dir, stdout=PIPE, stderr=PIPE, shell=self.use_shell) |
| |
| def _launch_local_presubmit_check(self, avd, test_method): |
| p1 = psutil.Popen([self.gradle, 'installDebug'], |
| cwd=self.uitest_dir, stdout=PIPE, stderr=PIPE, shell=self.use_shell) |
| p1.communicate() |
| p2 = psutil.Popen([self.gradle, 'installDebugAndroidTest'], |
| cwd=self.uitest_dir, stdout=PIPE, stderr=PIPE, shell=self.use_shell) |
| p2.communicate() |
| self.assertTrue(p1.poll() == 0 and p2.poll() == 0, "Failed to install the instrumentation APK.") |
| |
| p = psutil.Popen(['adb', 'shell', 'am', 'instrument', '-w', |
| '-e', 'class', test_method, |
| '-e', 'api', avd.api, '-e', 'abi', avd.abi, '-e', 'tag', avd.tag, '-e', 'origin', avd.ori, |
| 'com.android.devtools.systemimage.uitest.test/android.support.test.runner.AndroidJUnitRunner'], |
| cwd=self.uitest_dir, stdout=PIPE, stderr=PIPE, shell=self.use_shell) |
| (out, err) = p.communicate() |
| self.m_logger.info('instrumentation_test_stdout:\n' + out) |
| self.m_logger.info('instrumentation_test_stderr:\n' + err) |
| self.assertTrue(p.poll() == 0 and 'FAILURES!!!' not in out, "%s failed." % test_method) |
| |
| def ui_test_check(self, avd): |
| self.launch_emu_and_wait(avd) |
| self.m_logger.info('System image UI tests (%s) start.' % self._testMethodName) |
| if os.name is 'nt': |
| self.gradle = 'gradlew.bat' |
| self.use_shell = True |
| else: |
| self.gradle = './gradlew' |
| self.use_shell = False |
| self.uitest_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..', 'system_image_uitests') |
| |
| # install APKs required in UI tests |
| uitest_assets_dir = os.path.join(self.uitest_dir, 'app', 'src', 'main', 'assets') |
| for filename in os.listdir(uitest_assets_dir): |
| if filename.endswith('.apk'): |
| p = psutil.Popen(['adb', 'install', '-r', filename], cwd=uitest_assets_dir, stdout=PIPE, stderr=PIPE) |
| (out, err) = p.communicate() |
| self.m_logger.info('Install APK, stdout: %s, stderr: %s', out, err) |
| self.assertTrue(p.poll() == 0, "Failed to install %s." % filename) |
| |
| # check if it is a local presubmit test |
| if emu_args.uitest_psc is not None: |
| self._launch_local_presubmit_check(avd, emu_args.uitest_psc) |
| return |
| |
| # run tests using gradle script |
| proc = self._launch_ui_test_with_avd_configs(avd) |
| (out, err) = proc.communicate() |
| self.m_logger.info('gradle_stdout:\n' + out) |
| self.m_logger.info('gradle_stderr:\n' + err) |
| |
| # save gradle reports |
| self._save_gradle_test_report(self._testMethodName) |
| |
| # save adb bug reports for the bug report automation purpose |
| self._save_adb_bug_report(self._testMethodName) |
| |
| # pull detailed test case log info from android |
| self._pull_log_details(self._testMethodName) |
| |
| self.m_logger.info('System image UI tests (%s) end.' % self._testMethodName) |
| self.assertTrue(err is None or len(err.strip()) == 0, "The UI tests failed.") |
| |
| def run_ui_test(self, avd_config): |
| self.avd_config = avd_config |
| self.assertEqual(self.create_avd(avd_config), 0) |
| self.ui_test_check(avd_config) |
| |
| |
| if emu_args.config_file is None: |
| sys.exit(0) |
| else: |
| create_test_case_from_file("ui", UiAutomatorBaseTestCase, UiAutomatorBaseTestCase.run_ui_test) |
| |
| if __name__ == '__main__': |
| os.environ["SHELL"] = "/bin/bash" |
| emu_argparser.emu_args = emu_argparser.get_parser().parse_args() |
| print emu_argparser.emu_args |
| sys.argv[1:] = emu_args.unittest_args |
| unittest.main() |