예제 #1
0
def py_base_ex03():
    sys.path.append(os.getenv('PYPATH'))
    from utils import Constants
    from utils import LogManager
    from utils import SysUtils

    try:
        logger = LogManager.build_logger(Constants.LOG_FILE_PATH)
        logger.info('import external modules test.')
        utils = SysUtils().get_instance()
        utils.run_sys_cmd('python --version')
    finally:
        LogManager.clear_log_handles()
예제 #2
0
class MonkeyTest(object):
    '''
    Monkey test for APP, and collect APP and profile logs. 
    Pre-condition: login into APP before monkey test (by manual).
    '''

    # --------------------------------------------------------------
    # Init
    # --------------------------------------------------------------
    def __init__(self, test_pkg_name, run_mins):
        '''
        Constructor
        '''
        self.__test_pkg_name = test_pkg_name
        self.__run_mins = int(run_mins)

        cur_time = SysUtils.get_current_date_and_time()
        self.__log_root_path = os.path.join(os.getcwd(), 'monkeyreports')
        self.__log_dir_path_for_win = os.path.join(self.__log_root_path,
                                                   cur_time)
        self.__log_dir_path_for_shell = '/data/local/tmp/monkey_test_logs'

        self.__exec_log_path = os.path.join(self.__log_dir_path_for_win,
                                            'run_log.log')
        self.__device_props_file_path = os.path.join(
            self.__log_dir_path_for_win, 'device_props.log')
        self.__app_dump_file_path = os.path.join(self.__log_dir_path_for_win,
                                                 'app_info.log')
        self.__monkey_log_path_for_shell = '%s/%s' % (
            self.__log_dir_path_for_shell, 'monkey_log.log')
        self.__logcat_log_path_for_shell = '%s/%s' % (
            self.__log_dir_path_for_shell, 'logcat_full_log.log')

        self.__logcat_exception_file_name = 'logcat_exception.log'
        self.__logcat_exception_path_for_shell = '%s/%s' % (
            self.__log_dir_path_for_shell, self.__logcat_exception_file_name)
        self.__logcat_anr_file_name = 'logcat_anr.log'
        self.__logcat_anr_path_for_shell = '%s/%s' % (
            self.__log_dir_path_for_shell, self.__logcat_anr_file_name)

        SysUtils.create_dir(self.__log_dir_path_for_win)
        self.__logger = LogManager.build_logger(self.__exec_log_path)
        self.__sysutils = SysUtils()
        self.__adbutils = AdbUtils()
        self.__monitor = MonkeyMonitor()

        self.__profile_monitor = ProfileMonitor(
            Constants.ITEST_COLLECT_INTERVAL)
        self.__chart_parser = ChartParser(self.__log_dir_path_for_win)
        self.__report = MonkeyReport(self.__log_dir_path_for_win,
                                     self.__logcat_exception_file_name,
                                     self.__logcat_anr_file_name)

    # --------------------------------------------------------------
    # Monkey and logcat processes
    # --------------------------------------------------------------
    def __build_monkey_cmd(self):
        monkey_cmd = 'adb shell "monkey --throttle 500 -p %s' % self.__test_pkg_name

        monkey_launch_params = '-c android.intent.category.MONKEY -c android.intent.category.LAUNCHER -c ' + \
            'android.intent.category.DEFAULT --monitor-native-crashes --kill-process-after-error'
        monkey_ignore = ''
        if Constants.IS_MONKEY_CRASH_IGNORE:
            monkey_ignore = '--ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes'


#         monkey_actions_pct = '--pct-touch 65 --pct-motion 20 --pct-trackball 5 --pct-nav 0 ' + \
#             '--pct-majornav 5 --pct-syskeys 5 --pct-appswitch 0 --pct-flip 0 --pct-anyevent 0'
        monkey_actions_pct = self.__build_monkey_action_cmd()
        monkey_format = '-v -v -v %s > %s"' % (
            Constants.MONKEY_TOTAL_RUN_TIMES, self.__monkey_log_path_for_shell)

        return ' '.join((monkey_cmd, monkey_launch_params, monkey_ignore,
                         monkey_actions_pct, monkey_format))

    def __build_monkey_action_cmd(self):
        options = []
        options.append('--pct-touch ' + Constants.PCT_TOUCH)
        options.append('--pct-motion ' + Constants.PCT_MOTION)
        options.append('--pct-trackball ' + Constants.PCT_TRACKBALL)
        options.append('--pct-nav ' + Constants.PCT_NAV)
        options.append('--pct-majornav ' + Constants.PCT_MAJORNAV)
        options.append('--pct-syskeys ' + Constants.PCT_SYSKEYS)
        options.append('--pct-appswitch ' + Constants.PCT_APPSWITCH)
        options.append('--pct-anyevent ' + Constants.PCT_ANYEVENT)
        return ' '.join(options)

    def __run_monkey_subprocess(self):
        cmd = self.__build_monkey_cmd()
        self.__logger.info('Run monkey command: ' + cmd)
        return subprocess.Popen(cmd,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)

    def __run_logcat_subprocess(self):
        cmd = 'adb logcat -c && adb logcat -f %s -v threadtime *:%s' % (
            self.__logcat_log_path_for_shell, Constants.LOGCAT_LOG_LEVEL)
        return subprocess.Popen(cmd,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)

    # --------------------------------------------------------------
    # Adb and Shell utils
    # --------------------------------------------------------------
    def __create_log_dir_for_shell(self, dir_path):
        self.__check_adb_action(self.__adbutils.create_dir_on_shell(dir_path))

    def __clear_log_dir_for_shell(self):
        self.__check_adb_action(
            self.__adbutils.remove_files_on_shell(
                self.__log_dir_path_for_shell))

    def __check_adb_action(self, lines):
        for line in lines:
            if 'busy' in line:
                self.__logger.error(line)
                raise Exception('Monkey test exit because of device busy!')

    def __filter_shell_logcat_exception(self):
        cmd = 'adb shell \"cat %s | grep \'at com.jd.b2b\' -C 20 > %s"' % (
            self.__logcat_log_path_for_shell,
            self.__logcat_exception_path_for_shell)
        if not self.__sysutils.run_sys_cmd(cmd):
            self.__logger.warning('Filter exception for logcat failed!')

    def __filter_shell_logcat_anr(self):
        cmd = 'adb shell \"cat %s | grep \'E ANRManager: ANR\' -C 20 > %s"' % (
            self.__logcat_log_path_for_shell, self.__logcat_anr_path_for_shell)
        if not self.__sysutils.run_sys_cmd(cmd):
            self.__logger.warning('Filter anr for logcat failed!')

    def __pull_all_testing_logs(self):
        shell_log_files = (self.__logcat_log_path_for_shell,
                           self.__monkey_log_path_for_shell,
                           self.__logcat_exception_path_for_shell,
                           self.__logcat_anr_path_for_shell)
        for shell_f in shell_log_files:
            cmd_pull_log_files = 'adb pull %s %s' % (
                shell_f, self.__log_dir_path_for_win)
            if not self.__sysutils.run_sys_cmd(cmd_pull_log_files):
                self.__logger.warning('Pull logcat file failed: ' + shell_f)

        if not self.__adbutils.dump_tombstone_files(
                self.__log_dir_path_for_win):
            self.__logger.warning('Pull tombstone file failed!')

        self.__pull_latest_anr_files()

    def __pull_latest_anr_files(self):
        '''
        Get anr files in 24 hours.
        '''
        cmd = 'adb shell "find /data/anr/ -name *.txt -mtime -1 2>/dev/null"'
        anr_files = self.__sysutils.run_sys_cmd_and_ret_lines(cmd)
        if len(anr_files) == 0:
            return

        save_path = os.path.join(self.__log_dir_path_for_win, 'anr')
        self.__sysutils.create_dir(save_path)
        for f in anr_files:
            f = f.strip('\r\n')
            if len(f) == 0:
                continue
            cmd = 'adb pull %s %s' % (f, save_path)
            if not self.__sysutils.run_sys_cmd(cmd):
                self.__logger.warning('Pull anr file failed: ' + f)

    # --------------------------------------------------------------
    # Create report and archive
    # --------------------------------------------------------------
    def __create_monkey_test_report(self):
        title_dict = {}
        title_dict['TEST PACKAGE'] = self.__test_pkg_name
        title_dict['RUN TIME (minutes)'] = str(self.__run_mins)
        self.__report.create_monkey_test_report(title_dict)

    def __create_archive_report_file(self):
        time.sleep(1)
        root_dir = r'D:\JDTestLogs'  # temp local save path
        target_file = os.path.join(
            root_dir,
            'monkey_' + os.path.basename(self.__log_dir_path_for_win) + '.7z')
        cmd = r'"C:\Program Files\7-Zip\7z" a -t7z %s %s' % (
            target_file, self.__log_dir_path_for_win)

        self.__logger.debug('Create archive report file: ' + target_file)
        if not self.__sysutils.run_sys_cmd(cmd):
            self.__logger.warning('Create archive report file failed!')

    # --------------------------------------------------------------
    # Monkey Test Main
    # --------------------------------------------------------------
    def __is_profile_test_ok(self):
        return Constants.IS_PROFILE_TEST and int(
            self.__adbutils.get_android_version()[0]) < 7

    def __test_setup_main(self):
        if not self.__adbutils.is_devices_connected():
            raise Exception('No devices connected!')

        # shell env setup
        self.__adbutils.clear_anr_dir()
        self.__adbutils.clear_tombstone_dir()
        self.__clear_log_dir_for_shell()
        self.__create_log_dir_for_shell(self.__log_dir_path_for_shell)

        # win env setup
        self.__adbutils.dump_device_props(self.__device_props_file_path)
        self.__adbutils.dump_app_info(Constants.PKG_NAME_ZGB,
                                      self.__app_dump_file_path)

        if self.__is_profile_test_ok():
            self.__profile_monitor.start_monitor()

    def __test_main(self):
        self.__logger.info('Start logcat process.')
        logcat_p = self.__run_logcat_subprocess()
        self.__logger.info('Start monkey main process.')
        monkey_p = self.__run_monkey_subprocess()

        self.__logger.info('Start monkey monitor process.')
        monkey_monitor_t = threading.Thread(
            target=self.__monitor.process_monkey_monitor_main,
            args=(self.__run_mins, ))
        threads = []
        threads.append(monkey_monitor_t)
        if self.__is_profile_test_ok():
            self.__logger.info('Start APP profile monitor process.')
            profile_monitor_t = threading.Thread(
                target=self.__profile_monitor.running_monitor,
                args=(self.__run_mins, False, Constants.WAIT_TIME_IN_LOOP))
            threads.append(profile_monitor_t)

        for t in threads:
            t.start()
        for t in threads:
            t.join()

        monkey_p.kill()
        logcat_p.kill()

    def __test_clearup_main(self):
        # the adb connection maybe disconnect when running the monkey
        if self.__adbutils.is_devices_connected():
            self.__profile_monitor.stop_monitor()
            self.__adbutils.stop_app(self.__test_pkg_name)

            self.__filter_shell_logcat_exception()
            self.__filter_shell_logcat_anr()
            self.__pull_all_testing_logs()
            self.__create_monkey_test_report()

            if self.__is_profile_test_ok():
                time.sleep(1)
                self.__profile_monitor.pull_itest_logfiles(
                    self.__log_dir_path_for_win)
                self.__chart_parser.build_all_profile_charts()
        else:
            self.__logger.error('Device disconnect!')
        LogManager.clear_log_handles()

        if Constants.IS_CREATE_ARCHIVE:
            self.__create_archive_report_file()

    def mokeytest_main(self):
        self.__test_setup_main()
        self.__test_main()
        self.__test_clearup_main()
예제 #3
0
class ProfileMonitor(object):
    '''
    Android app profile monitor by iTest.
    Pre-conditions: APP under test is added into iTest, and set data collect interval configs (by manual), prefer 3s.
    '''

    __itest_pkg_name = 'iflytek.testTech.propertytool'
    __itest_boot_act = 'iflytek.testTech.propertytool.activity.BootActivity'
    __log_root_dir_path = '/sdcard/AndroidPropertyTool4'
    __hand_log_dir = 'handTest'
    __hand_log_dir_path = __log_root_dir_path + '/' + __hand_log_dir

    def __init__(self, itest_collect_interval):
        '''
        Constructor
        '''
        self.__is_stopped = True
        self.__logger = LogManager.get_logger()
        self.__sys_utils = SysUtils()
        self.__adb_utils = AdbUtils()
        # note: this value should be greater than interval config in iTest
        self.__wait_time_between_check = itest_collect_interval + 1

    # --------------------------------------------------------------
    # Start Monitor
    # --------------------------------------------------------------
    def start_monitor(self):
        self.__clear_itest_logs()
        self.__launch_itest()
        time.sleep(2)
        self.__click_itest_monitor_btn()
        time.sleep(1)
        if not self.__is_itest_logfile_created():
            raise Exception('start iTest monitor failed!')
        self.__is_stopped = False

    def __clear_itest_logs(self):
        cmd = 'adb shell "cd %s;rm -rf %s*"' \
            % (self.__log_root_dir_path, self.__hand_log_dir)
        if not self.__sys_utils.run_sys_cmd(cmd):
            raise Exception('clear iTest log files failed!')

    def __launch_itest(self):
        cmd = 'adb shell am start ' + self.__itest_pkg_name + '/' + self.__itest_boot_act
        self.__sys_utils.run_sys_cmd(cmd)

        for i in range(0, 3):
            if self.__adb_utils.is_package_on_top(self.__itest_pkg_name):
                return
            time.sleep(1)
        raise Exception('launch iTest app failed!')

    def __is_itest_logfile_created(self):
        cmd = 'adb shell "cd %s;ls|grep %s"' \
            % (self.__log_root_dir_path, self.__hand_log_dir)
        return len(self.__sys_utils.run_sys_cmd_and_ret_content(cmd)) != 0

    def __click_itest_monitor_btn(self):
        cmd = 'adb shell input tap 800 1880'
        return self.__sys_utils.run_sys_cmd(cmd)

    # --------------------------------------------------------------
    # Running Monitor
    # --------------------------------------------------------------
    def running_monitor(self, run_mins, is_end_with_stop=True, interval=15):
        run_secs = run_mins * 60
        start = time.perf_counter()
        while 1:
            time.sleep(interval)
            if not self.__is_itest_running():
                self.__logger.error('iTest process is NOT running!')
                return
            if time.perf_counter() - start >= run_secs and self.__is_itest_running():
                if is_end_with_stop:
                    self.stop_monitor()
                    self.__is_stopped = True
                return

    def __is_itest_process_running(self):
        cmd = 'adb shell "ps | grep %s"' % self.__itest_pkg_name
        if len(self.__sys_utils.run_sys_cmd_and_ret_content(cmd)) == 0:
            return False
        return True

    def __is_cpu_logfile_updated(self):
        before_record_time = self.__get_cpu_logfile_record_time()
        self.__logger.info('before time: ' + before_record_time)
        time.sleep(self.__wait_time_between_check)
        after_record_time = self.__get_cpu_logfile_record_time()
        self.__logger.info('after time: ' + after_record_time)
        return before_record_time != after_record_time

    def __get_cpu_logfile_record_time(self):
        file_name = 'cpuSystem.txt'
        cmd = 'adb shell "cd %s;tail -n 1 %s"' \
            % (self.__hand_log_dir_path, file_name)
        last_line = self.__sys_utils.run_sys_cmd_and_ret_content(cmd)
        return last_line.split()[0]  # record time

    def __is_itest_running(self):
        if self.__is_itest_process_running() and self.__is_cpu_logfile_updated():
            return True
        return False

    # --------------------------------------------------------------
    # Stop Monitor and pull logs
    # --------------------------------------------------------------
    def stop_monitor(self):
        if self.__is_stopped:
            return

        self.__launch_itest()
        time.sleep(2)  # wait to fix action failed
        self.__click_itest_monitor_btn()
        time.sleep(1)
        self.__force_stop_itest()
        self.__is_stopped = True

    def __force_stop_itest(self):
        cmd = 'adb shell am force-stop ' + self.__itest_pkg_name
        self.__sys_utils.run_sys_cmd(cmd)

    def __clear_local_itest_logs(self, dir_path):
        SysUtils.delete_files_in_dir(dir_path)

    def pull_itest_logfiles(self, local_save_path):
        if len(local_save_path) == 0:
            self.__logger.warn('skip dump iTest logs!')
            return

        self.__clear_local_itest_logs(os.path.join(local_save_path, self.__hand_log_dir))
        cmd = 'adb pull %s %s' % (self.__hand_log_dir_path, local_save_path)
        if not self.__sys_utils.run_sys_cmd(cmd):
            self.__logger.error('dump iTest logs failed!')