当前位置:Gxlcms > 数据库问题 > [python测试框架学习篇] 分享一个和adb相关的测试框架

[python测试框架学习篇] 分享一个和adb相关的测试框架

时间:2021-07-01 10:21:17 帮助过:5人阅读

1 · 2017年01月13日 小小的建议 没缩进不能看,不如贴gist 单纯的adb的封装有很多人写了 比如我(#厚脸皮) https://github.com/264768502/adb_wrapper 比如这贴: https://testerhome.com/topics/6938 如果要处理UI的话,其实有现成的,比如pyuiautomator或者Appium 96 yaboandriod · #2 · 2017年01月16日 controller代码 import xml.etree.ElementTree as ET import os import sys import subprocess as sp import time import logging import re import codecs import datetime import ui_hooks import socket import threading WINDOW_FACTOR = [index, text, resource-id, class, package, visible, content-desc, checkable, checked, clickable, enabled, focusable, focused, scrollable, long-clickable, password, bottom, selected, bounds] RETRY_MAX_TIME = 3 def get_data(address): result={} temp = ‘‘ f1 = open(address,r) temp = f1.read() result = eval(temp) f1.close() return result class Operator: def __init__(self,device_id=‘‘,log_class=None,log_path=‘‘,**kwargs): self.device_id = device_id self.log_class = log_class self.log_path = log_path self.current_path = os.path.dirname(__file__) self.home_dir = os.path.expanduser(~) if not os.path.isdir(self.log_path): try: os.makedirs(log_path) except OSError: pass self.failure_pic_location = os.path.join(self.log_path,screenshots) if not os.path.isdir(self.failure_pic_location): try: os.makedirs(self.failure_pic_location) except OSError: pass self.temporary = os.path.join(self.log_path,temp) if not os.path.isdir(self.temporary): try: os.makedirs(self.temporary) except OSError: pass self.hooks = ui_hooks.Hooks(self.device_id) def get_instance(self): op = Operator(self.device_id,self.log_class,self.log_path) return op def decode_utf(self,var): utype = codecs.lookup("utf-8") return utype.decode(var)[0] def update_dictory(self,dictory): keys_list = dictory.keys() values_list = dictory.values() temp={} for i in range(len(keys_list)): temp[keys_list[i]] = self.decode_utf(values_list[i]) return temp def search(self,**kwargs): global paras_dictory,retry_time temp = kwargs paras_dictory = self.update_dictory(temp) if paras_dictory.has_key("retry_time"): retry_time = paras_dictory["retry_time"] else: retry_time = None return self.judge(paras_dictory,retry_time) def judge(self,dic,retry_time): timer = 0 global xml_path xml_path = self.get_xml() if xml_path is None: print "Error : can not generate window dump file." panel = None return panel else: self.native_unlock_screen() if retry_time is not None: while 1: if timer < int(retry_time): if self.parse_window_dump(paras_dictory) is None: print "Warnning : there is no view or many views match your require, retry again!" self.little_swipe() time.sleep(1) timer+=1 self.judge(paras_dictory,retry_time) else: op = self.get_instance() panel = Panel(op) return panel break else: panel = None return panel else: if self.parse_window_dump(paras_dictory) is None: print "Warnning : there is no view or many views match your require, start to search hooks library...!" self.hooks.get_generators(self.get_all_nodes()) status = self.hooks.parse() # if status is True, it means find corresponding frame and click next button to skip this frame if status: time.sleep(1) self.judge(paras_dictory,retry_time).click() else: panel = None return panel else: op = self.get_instance() panel = Panel(op) return panel def get_intents_dictory(self): bluesea_dir = os.path.abspath(os.path.join(self.current_path,os.pardir)) app_intents_file_path = os.path.join(bluesea_dir,repository/intent_list.cfg) return get_data(app_intents_file_path) def hardware(self,**kwargs): executor = self.get_instance() dut = Device(executor) return dut def get_all_nodes(self): parser = ET.parse(xml_path) root = parser.getroot() node_instance_list = root.iter(node) return node_instance_list def get_scrollable_view(self): for ins in self.get_all_nodes(): if ins.attrib["scrollable"] == "true": bound = ins.get("bounds") break else: bound = None return bound def native_is_screen_lock(self): is_screen_lock = False for ins in self.get_all_nodes(): id_collector = ins.attrib[resource-id] if "id/lock_icon" in id_collector.strip(\n): is_screen_lock = True break return is_screen_lock def parse_window_dump(self,parametres=None): r1 = r[A-Za-z]+:id/(\w+) bound = None p_counter = [] bound_list = [] counter_id = 0 counter_index = 0 counter_desc = 0 counter_pack = 0 counter_text = 0 counter_enabled = 0 false_flag = 0 if parametres.has_key(id): view_id = parametres[id] p_counter.append(view_id) if parametres.has_key(text): view_text = parametres[text] p_counter.append(view_text) if parametres.has_key(description): view_description = parametres[description] p_counter.append(view_description) if parametres.has_key(index): view_index = parametres[index] p_counter.append(view_index) if parametres.has_key(package): view_package = parametres[package] p_counter.append(view_package) if parametres.has_key(enabled): view_enabled = parametres[enabled] p_counter.append(view_enabled) if len(p_counter) == 0: print "Error : invalid input, there is no useful parameter given!!!" sys.exit(-1) for factor in self.get_all_nodes(): id_collector = factor.attrib[resource-id] text_collector = factor.attrib[text] index_collector = factor.attrib[index] desc_collector = factor.attrib[content-desc] pack_collector = factor.attrib[package] enabled_collector = factor.attrib[enabled] for your_input in p_counter: id_strs = re.findall(r1,id_collector.strip(\n)) id_string = id_strs if not id_strs == []: id_string=id_strs[0] else: id_string = id_collector.strip(\n\r) if your_input == id_string: bound_id = factor.get("bounds") counter_id +=1 if your_input == text_collector.strip(\n): bound_text = factor.get("bounds") counter_text +=1 if your_input == index_collector.strip(\n): bound_index = factor.get("bounds") counter_index +=1 if your_input == desc_collector.strip(\n): bound_desc = factor.get("bounds") counter_desc +=1 if your_input == pack_collector.strip(\n): bound_pack = factor.get("bounds") counter_pack +=1 if your_input == enabled_collector.strip(\n): bound_enabled = factor.get("bounds") counter_enabled +=1 if counter_id == 0: false_flag += 1 if counter_index == 0: false_flag += 1 if counter_pack == 0: false_flag += 1 if counter_desc == 0: false_flag += 1 if counter_text == 0: false_flag += 1 if counter_enabled == 0: false_flag += 1 if counter_id == 1: bound_list.append(bound_id) if counter_text == 1: bound_list.append(bound_text) if counter_desc == 1: bound_list.append(bound_desc) if counter_pack == 1: bound_list.append(bound_pack) if counter_index == 1: bound_list.append(bound_index) if counter_enabled == 1: bound_list.append(bound_enabled) if false_flag <= 6 - len(p_counter): if len(bound_list) == 0: bound = None elif len(bound_list) == 1: bound = bound_list[0] elif len(bound_list) == 2: temp_bound = bound_list[0] if bound_list[1] == temp_bound: bound = temp_bound else: bound = None elif len(bound_list) > 2: temp_bound = bound_list[0] for bo in range(1,len(bound_list)): if bound_list[bo] != temp_bound: bound = None break else: bound = temp_bound else: bound = None return bound def get_xml(self): retry_count = 0 while 1: if retry_count < RETRY_MAX_TIME: self.adb_root() shell_cmd = self.adb_shell() dump_xml_command = shell_cmd + uiautomator dump /sdcard/window_dump.xml self.execute_command(dump_xml_command).wait() xml_file_on_device_path = /sdcard/window_dump.xml xml_file_on_server_path = self.temporary xml_file_origin = os.path.join(xml_file_on_server_path,window_dump.xml) xml_new_name = self.device_id + _ + window_dump.xml xml_file = os.path.join(xml_file_on_server_path,xml_new_name) get_xml_command = adb -s + self.device_id + pull + xml_file_on_device_path + + xml_file_on_server_path self.execute_command(get_xml_command).wait() try: os.rename(xml_file_origin,xml_file) except OSError as oer: print oer self.get_xml() if os.path.isfile(xml_file): return xml_file break else: retry_count += 1 else: print "Unkown issue of adb, uiautomator dump file failed!" break return def adb_root(self): root_command = adb -s + self.device_id + root self.execute_command(root_command).wait() def generate_folder_locate_picture(self): address_picture = self.failure_pic_location if not os.path.isdir(address_picture): try: os.makedirs(address_picture) except OSError: pass return address_picture def generate_screenshot_name_format(self): dt = datetime.datetime.now().strftime(%Y_%m_%d_%H_%M_%S) file_name = screenshot_ + dt + .png return file_name def adb_command(self): adb_command = adb -s + self.device_id + return adb_command def adb_shell(self): adb_shell_command = adb -s + self.device_id + shell return adb_shell_command def execute_command(self,cmd,ignore_print=True): ccmd = cmd if ignore_print: self.log_class.info("Execute command : {0}".format(ccmd)) else: pass proc = sp.Popen(ccmd.split( ),stdout=sp.PIPE) return proc def check_adb_works(self,proc): pass def get_dumpsys_display(self): dumpsys_display_command = self.adb_shell() + dumpsys display out = self.execute_command(dumpsys_display_command) lines = out.stdout.read().split(\n) return lines def bound_to_list(self): s = self.parse_window_dump(paras_dictory) temp = s.replace([,‘‘).replace(],,).split(,) temp.remove(‘‘) return temp def get_centre_coordinate(self): c_list = self.bound_to_list() point_c = [] co_x1 = c_list[0] co_x2 = c_list[2] point_c.append(str((int(co_x1)+int(co_x2))/2)) co_y1 = c_list[1] co_y2 = c_list[3] point_c.append(str((int(co_y1)+int(co_y2))/2)) return point_c def native_power_on(self): if not self.native_check_screen_on(): power_on_command = self.adb_shell() + input keyevent 26 self.execute_command(power_on_command).wait() def native_unlock_screen(self): self.native_power_on() if self.native_is_screen_lock(): self.native_push_up() def native_check_screen_on(self): is_screen_on = False for line in self.get_dumpsys_display(): if mScreenState in line and ON in line: is_screen_on = True return is_screen_on def native_push_up(self): device_resolution = self.get_max_resolution() max_w = device_resolution[0] max_h = device_resolution[1] if max_w ==unknow or max_h ==unknow: print "Error : dumpsys display failed" sys.exit(-1) else: x1 = str(int(max_w)/2) x2 = str(int(max_w)/2) y1 = str((int(max_h)*4)/5) y2 = str(int(max_h)/5) push_up_command = self.adb_shell() + input swipe + x1 + + y1 + + x2 + + y2 self.execute_command(push_up_command).wait() def get_max_resolution(self): max_resolution = [] for line in self.get_dumpsys_display(): if mDisplayWidth in line: max_resolution.append(line.strip(\r).split(=)[-1]) if mDisplayHeight in line: max_resolution.append(line.strip(\r).split(=)[-1]) return max_resolution def take_snapshot(self): global xml_path xml_path=self.get_xml() file_path = self.generate_folder_locate_picture() picture_name = self.generate_screenshot_name_format() uiautomator_dump_file_name = picture_name.split(.)[0] + .uix uiautomator_dump_file = os.path.join(file_path,uiautomator_dump_file_name) file_path_device = os.path.join(/sdcard/ + picture_name) take_snapshot_command = self.adb_shell() + /system/bin/screencap -p + file_path_device pull_snapshot_command = adb -s + self.device_id + pull + file_path_device + + file_path get_uiautomator_dump_command = self.adb_shell() + uiautomator dump pull_uiautomator_dump_command = adb -s + self.device_id + pull /sdcard/window_dump.xml + + uiautomator_dump_file self.native_unlock_screen() time.sleep(0.5) self.execute_command(take_snapshot_command).wait() self.execute_command(pull_snapshot_command).wait() self.execute_command(get_uiautomator_dump_command).wait() self.execute_command(pull_uiautomator_dump_command).wait() def little_swipe(self): device_resolution_2 = self.get_max_resolution() max_w_2 = device_resolution_2[0] max_h_2 = device_resolution_2[1] x1_2 = str(int(max_w_2)/2) x2_2 = str(int(max_w_2)/2) y2_2 = str((int(max_h_2)*2)/5) y1_2 = str((int(max_h_2)*4)/5) little_swipe_command = self.adb_shell() + input swipe + x1_2 + + y1_2 + + x2_2 + + y2_2 self.execute_command(little_swipe_command).wait() class Device(object): def __init__(self,executor): self.executor = executor def return_home(self): go_home_command = self.executor.adb_shell() + input keyevent 3 self.executor.execute_command(go_home_command).wait() def press_enter(self): press_enter_command = self.executor.adb_shell() + input keyevent 66 self.executor.execute_command(press_enter_command).wait() def press_menu(self): press_menu_command = self.executor.adb_shell() + input keyevent 82 self.executor.execute_command(press_menu_command).wait() def shift_tab(self,counter=1): tab_key = 61 shift_tab_command = self.executor.adb_shell() + input keyevent + (tab_key*int(counter)).strip() self.executor.execute_command(shift_tab_command).wait() def shift_down(self,counter=1): down_key = 20 press_down_command = self.executor.adb_shell() + input keyevent + (down_key*int(counter)).strip() self.executor.execute_command(press_down_command).wait() def shift_up(self,counter=1): up_key = 19 press_up_command = self.executor.adb_shell() + input keyevent + (up_key*int(counter)).strip() self.executor.execute_command(press_up_command).wait() def shift_left(self,counter=1): press_left_command = self.executor.adb_shell() + input keyevent 21 for j in range(int(counter)): self.executor.execute_command(press_left_command).wait() time.sleep(1) def volume_up(self,counter=1): volume_up_command = self.executor.adb_shell() + input keyevent 24 for j in range(int(counter)): self.executor.execute_command(volume_up_command).wait() time.sleep(0.5) def volume_down(self,counter=1): volume_down_command = self.executor.adb_shell() + input keyevent 25 for j in range(int(counter)): self.executor.execute_command(volume_down_command).wait() time.sleep(0.5) def shift_right(self,counter=1): press_right_command = self.executor.adb_shell() + input keyevent 22 for k in range(int(counter)): self.executor.execute_command(press_right_command).wait() time.sleep(1) def push_up(self): device_resolution = self.executor.get_max_resolution() max_w = device_resolution[0] max_h = device_resolution[1] if max_w ==unknow or max_h ==unknow: print "Error : dumpsys display failed" sys.exit(-1) else: x1 = str(int(max_w)/2) x2 = str(int(max_w)/2) y1 = str((int(max_h)*4)/5) y2 = str(int(max_h)/5) push_up_command = self.executor.adb_shell() + input swipe + x1 + + y1 + + x2 + + y2 self.executor.execute_command(push_up_command).wait() def swipe_right(self): device_resolution = self.executor.get_max_resolution() max_w = device_resolution[0] max_h = device_resolution[1] if max_w ==unknow or max_h ==unknow: print "Error : dumpsys display failed" sys.exit(-1) else: x1 = str(int(max_w)/5) x2 = str((int(max_w)*4)/5) y1 = str(int(max_h)/2) y2 = str(int(max_h)/2) swipe_right_command = self.executor.adb_shell() + input swipe + x1 + + y1 + + x2 + + y2 self.executor.execute_command(swipe_right_command).wait() def check_boot_status(self): is_booted = False check_boot_status_command = self.executor.adb_shell() + getprop grep_command = grep bootanim p5 = sp.Popen(check_boot_status_command.split( ),stdout=sp.PIPE) p6 = sp.Popen(grep_command.split( ),stdin=p5.stdout,stdout=sp.PIPE) out = p6.stdout.read().strip(\n) if "stopped" and 1 in out: is_booted = True return is_booted def check_reboot_progress(self): reboot_execute_success = False if not self.check_boot_status(): reboot_execute_success = True return reboot_execute_success def reboot_device(self): reboot_device_command = self.executor.adb_command() + reboot self.executor.execute_command(reboot_device_command).wait() def input_text(self,string=%s): string = string.strip().replace( ,%s) input_text_command = self.executor.adb_shell() + input text + string self.executor.execute_command(input_text_command).wait() def swipe_left(self): device_resolution = self.executor.get_max_resolution() max_w = device_resolution[0] max_h = device_resolution[1] if max_w ==unknow or max_h ==unknow: print "Error : dumpsys display failed" sys.exit(-1) else: x1 = str((int(max_w)*4)/5) x2 = str(int(max_w)/5) y1 = str(int(max_h)/2) y2 = str(int(max_h)/2) swipe_left_command = self.executor.adb_shell() + input swipe + x1 + + y1

人气教程排行