def _current_resmgr_session(): tc = context.current_testcase() if tc is None: logger.warn("注意!非用例模式,将返回默认测试文件资源管理器,此处调用可能在测试环境下异常") return TestResourceManager( LocalResourceManagerBackend()).create_session() return tc.test_resources
def post_test(self): '''清理测试用例 ''' self._run_test_complete = True if hasattr(self, '_record_thread_status_dict' ) and self._record_thread_status_dict: timeout = 30 time0 = time.time() while time.time() - time0 < timeout: for key in self._record_thread_status_dict: if not self._record_thread_status_dict[key]: break else: break time.sleep(0.1) else: qta_logger.warn('wait for record screen thread exit timeout') self._save_logcat() self._save_qt4a_log() if hasattr(self, '_logcat_debug_level_list'): for device in Device.device_list: device_name = '%s' % device.device_id if device_name not in self._logcat_debug_level_list: msg = '设备:%s中的logcat没有debug级别的日志,请检查手机日志级别设置 ' % device_name if self._check_log_called: qta_logger.error(msg) else: qta_logger.warn(msg) if hasattr(settings, 'QT4A_DEVICE_HOSTS'): for device in Device.device_list: self.log_info('恢复设备: %s hosts环境' % device.device_id) device.modify_hosts()
def _load(self): '''加载配置 :returns: Settings - 设置读取接口 ''' # get PROJECT_MODE from user settings default_mode = getattr(qtaf_settings, 'PROJECT_MODE', None) try: pre_settings = self._load_proj_settings_module( "testbase.conf.pre_settings") mode = getattr(pre_settings, "PROJECT_MODE", default_mode) except ImportError as e: pre_settings = None if os.path.isfile(__file__): mode = "standard" else: mode = "standalone" if mode == "standard": # library mode proj_root = getattr(pre_settings, "PROJECT_ROOT", os.getcwd()) installed_apps = getattr( pre_settings, "INSTALLED_APPS", getattr(qtaf_settings, 'INSTALLED_APPS', [])) else: # egg mode proj_root = self._get_standalone_project_root(pre_settings) installed_apps = ExLibManager(proj_root).list_names() # load settings from qtaf self._load_setting_from_module(qtaf_settings) # load settings from installed apps for appname in installed_apps: modname = "%s.settings" % appname try: __import__(modname) except: stack = traceback.format_exc() logger.warn( "[WARN]load library settings module \"%s\" failed:\n%s" % (modname, stack)) else: self._load_setting_from_module(sys.modules[modname]) # load settings from user settings try: proj_settings = self._load_proj_settings_module( "testbase.conf.settings") except ImportError as e: if e.args[0] not in [ "No module named settings", "No module named 'settings'" ]: # project settings found and there was an error stack = traceback.format_exc() logger.warn("[WARN]load project settings failed:\n%s" % stack) else: self._load_setting_from_module(proj_settings) # trying to set project root automatically setattr(self, "PROJECT_ROOT", proj_root) setattr(self, "INSTALLED_APPS", installed_apps)
def _load(self): '''加载配置 :returns: Settings - 设置读取接口 ''' # get PROJECT_MODE from user settings try: pre_settings = self._load_proj_settings_module( "testbase.conf.pre_settings") except ImportError as e: logger.warn("[WARNING]settings module not found: %s" % str(e)) pre_settings = None mode = getattr(pre_settings, "PROJECT_MODE", getattr(qtaf_settings, 'PROJECT_MODE', None)) if mode == "standard": # library mode installed_apps = getattr( pre_settings, "INSTALLED_APPS", getattr(qtaf_settings, 'INSTALLED_APPS', [])) else: # egg mode proj_root = self._get_standalone_project_root(pre_settings) installed_apps = ExLibManager(proj_root).list_names() # load settings from qtaf self._load_setting_from_module(qtaf_settings) # load settings from installed apps for appname in installed_apps: modname = "%s.settings" % appname try: __import__(modname) except ImportError as e: logger.warn( "[WARN]load library settings module \"%s\" failed: %s" % (modname, str(e))) else: self._load_setting_from_module(sys.modules[modname]) # load settings from user settings try: proj_settings = self._load_proj_settings_module( "testbase.conf.settings") except ImportError: pass else: self._load_setting_from_module(proj_settings) # trying to set project root automatically if mode != "standard": self.PROJECT_ROOT = proj_root self.INSTALLED_APPS = ExLibManager(proj_root).list_names() else: proj_root = getattr(self, "PROJECT_ROOT", None) if pre_settings is not None and not proj_root: proj_root = os.path.dirname(pre_settings.__file__) setattr(self, "PROJECT_ROOT", proj_root)
def load_datadrive_tests(cls, name=None, exclude_data_key=None, attrs=None): '''加载对应数据驱动测试用例类的数据驱动用例 ''' if is_datadrive(cls): dd = get_datadrive(cls) else: if not settings.DATA_DRIVE: raise RuntimeError("DATA_DRIVE is not set to True") from testbase.loader import TestDataLoader dd = TestDataLoader().load() if name: if name in dd: drive_data = {name : dd[name]} else: drive_value = _get_translated_in_datadrive(name, dd) drive_data = {name : drive_value} else: drive_data = dd if exclude_data_key is None: exclude_data_key = [] exclude_data_key = [_translate_bad_char4exclude_keys(item) for item in exclude_data_key] tests = [] for item in drive_data: # 如果有排除标签 exclude_item = _translate_bad_char4exclude_keys(item) if exclude_data_key is not None and exclude_item in exclude_data_key: continue testdata = drive_data[item] if isinstance(item, six.string_types): item = smart_text(item) else: item = str(item) casedata_name = item if has_bad_char(item): casedata_name = translate_bad_char(item) warn_msg = "[WARNING]%r's drive data key should use \"%s\" instead of \"%s\"" % (cls, casedata_name, item) logger.warn(warn_msg) if isinstance(testdata, dict) and "__attrs__" in testdata: new_attrs = testdata.get("__attrs__") else: new_attrs = None if attrs: if not new_attrs: new_attrs = attrs else: new_attrs.update(attrs) tests.append(cls(testdata, casedata_name, new_attrs)) return tests
def acquire_device(self, device_id=None, **kwargs): '''申请设备接口 :param device_id: 设备ID,用于本地调试 :type device_id: string ''' if device_id: kwargs['id'] = device_id resource = self.test_resources.acquire_resource('android', condition=kwargs) device = DeviceProviderManager().connect_device(resource) if not device: raise RuntimeError('Connect device %s failed' % resource) try: self.test_result.log_record( EnumLogLevel.Environment, '申请 %s 设备成功:%s(%s)' % ('Android', device.model, device.device_id), {"device": device.imei}) except Exception as e: qta_logger.warn('GetDeviceImei error:%s' % e) if hasattr(settings, 'QT4A_DEVICE_HOSTS'): device_hosts = settings.QT4A_DEVICE_HOSTS if device_hosts: self.logInfo('设置设备hosts为:\n%s' % device_hosts) host_list = [] pattern = re.compile(r'\s*(\S+)\s+(\S+)\s*') for line in device_hosts.split('\n'): line = line.strip() if not line: continue ret = pattern.match(line) if not ret: raise RuntimeError('hosts格式错误: %r' % line) host_list.append((ret.group(1), ret.group(2))) device.modify_hosts(host_list) self.add_logcat_callback(device) if hasattr( settings, 'QT4A_RECORD_SCREEN') and settings.QT4A_RECORD_SCREEN == True: if not hasattr(self, '_record_thread_status_dict'): self._record_thread_status_dict = {} self._record_thread_status_dict[device.device_id] = False qta_logger.info('%s start record screen thread' % device.device_id) t = util.ThreadEx(target=self._record_screen_thread, args=(device, ), name='Device Record Screen Thread') t.setDaemon(True) t.start() device.adb.start_logcat() return device
def _record_screen_thread(self, device): '''录屏线程 ''' from androiddriver.devicedriver import qt4a_path record_time = 4 * 1000 # 每次录制的时间 framerate = 8 quality = 20 remote_tmp_path_tmpl = '%s/screen.record.%%d' % qt4a_path max_record_file_count = 4 # 最大临时存储的录屏文件数目 index = 0 device.delete_file('%s/screen.record.*' % qt4a_path) while not hasattr( self, '_run_test_complete') or self._run_test_complete == False: # 尚未结束 remote_tmp_path = remote_tmp_path_tmpl % (index % max_record_file_count) device.run_shell_cmd( '%s/screenshot record -p %s -t %d -f %d -q %d' % (qt4a_path, remote_tmp_path, record_time, framerate, quality)) index += 1 if index >= max_record_file_count: index -= max_record_file_count if not self.test_result.passed: merge_file_list = [] for i in range(max_record_file_count): merge_file_list.append(remote_tmp_path_tmpl % ((i + index) % max_record_file_count)) device.run_shell_cmd( 'cat %s > %s' % (' '.join(merge_file_list), remote_tmp_path_tmpl % max_record_file_count)) local_tmp_path = tempfile.mktemp('.record') device.pull_file(remote_tmp_path_tmpl % max_record_file_count, local_tmp_path) save_dir = tempfile.mkdtemp('.screenshot') frame_list = Device.extract_record_frame(local_tmp_path, save_dir) video_path = self.__class__.__name__ + '_' + get_valid_file_name( device.device_id) + '_' + str(int(time.time())) + '.mp4' result = Device.screen_frame_to_video(frame_list, framerate, video_path) if result == None: qta_logger.warn('opencv not installed') else: self.test_result.info('最近15秒录屏', attachments={video_path: video_path}) shutil.rmtree(save_dir) self._record_thread_status_dict[device.device_id] = True
def __init_runner_types(): global runner_types if runner_types: return runner_types["basic"] = TestRunner runner_types["multithread"] = ThreadingTestRunner runner_types["multiprocess"] = MultiProcessTestRunner for ep in pkg_resources.iter_entry_points(RUNNER_ENTRY_POINT): if ep.name not in runner_types: try: runner_types[ep.name] = ep.load() except: stack = traceback.format_exc() logger.warn("load TestRunner type for %s failed:\n%s" % (ep.name, stack))
def load_datadrive_tests(cls, name=None): '''加载对应数据驱动测试用例类的数据驱动用例 ''' if is_datadrive(cls): dd = get_datadrive(cls) else: if not settings.DATA_DRIVE: raise RuntimeError("DATA_DRIVE is not set to True") from testbase.loader import TestDataLoader dd = TestDataLoader().load() if name: if name in dd: drive_data = {name: dd[name]} else: drive_value = _get_translated_in_datadrive(name, dd) drive_data = {name: drive_value} else: drive_data = dd tests = [] for item in drive_data: testdata = drive_data[item] if isinstance(item, six.string_types): item = smart_text(item) else: item = str(item) casedata_name = item if has_bad_char(item): casedata_name = translate_bad_char(item) warn_msg = "[WARNING]%r's drive data should use \"%s\" instread of \"%s\"" % ( cls, casedata_name, item) logger.warn(warn_msg) if isinstance(testdata, dict) and "__attrs__" in testdata: attrs = testdata.get("__attrs__") else: attrs = None tests.append(cls(testdata, casedata_name, attrs)) return tests
def acquire_device(self, device_id=None, **kwargs): '''申请设备接口 :param device_id: 设备ID,用于本地调试 :type device_id: string ''' if device_id: kwargs['id'] = device_id resource = self.test_resources.acquire_resource('android', condition=kwargs) device = DeviceProviderManager().connect_device(resource) if not device: raise RuntimeError('Connect device %s failed' % resource) try: self.test_result.log_record( EnumLogLevel.Environment, '申请 %s 设备成功:%s(%s)' % ('Android', device.model, device.device_id), {"device": device.imei}) except Exception, e: qta_logger.warn('GetDeviceImei error:%s' % e)
def __init_report_types(): global report_types if report_types: return report_types.update({ "empty": EmptyTestReport, "stream": StreamTestReport, "xml": XMLTestReport, "json": JSONTestReport, "html": HtmlTestReport, }) # Register other `ITestReport` implementations from entry points for ep in pkg_resources.iter_entry_points(REPORT_ENTRY_POINT): if ep.name not in report_types: try: report_types[ep.name] = ep.load() except: stack = traceback.format_exc() logger.warn("load ITestReport entry point for %s failed:\n%s" % (ep.name, stack))