定位方式
1.通过id定位
self.driver.find_element(“id”,“com.stnts.iyoucloud:id/iv_home_message”)
2.通过xpath定位
2.1属性定位
self.driver.find_element(“xpath”,“//android.widget.LinearLayout[@content-desc=\’游戏库\’]”)
2.2contains模糊定位
self.driver.find_element(“xpath”,“//android.widget.TextView[contains(@text ,'热门游戏')]”)
2.3组合定位
self.popular_game_list_second_game = (By.XPATH, '//*[@text="2" and @resource-id="com.stnts.iyoucloud:id/item_num"]')
2.4层级定位
self.game_library_first_game = (By.XPATH, "//androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout[1]")
3.通过坐标定位
size_tmp = self.driver.get_window_size()
self.driver.tap([(135 / 1080 * size_tmp['width'], 385 / 1920 * size_tmp['height'])], 3)
实用方法
1.判断元素是否存在
def is_element_exist(self, identify_by, what, timeout=ConfigData().implicitly_wait_time()): """ 如果元素存在,即返回该元素 """ element_exist = None self.driver.implicitly_wait(timeout) try: if identify_by in [By.ID, By.XPATH, By.CLASS_NAME, By.LINK_TEXT, By.PARTIAL_LINK_TEXT, By.NAME, By.TAG_NAME, By.CSS_SELECTOR]: element_exist = self.driver.find_element(identify_by, what) except: element_exist = False finally: timeout = ConfigData().implicitly_wait_time() return element_exist
2.显式等待元素,存在则返回
def element_visible(self, loc, timeout=20, poll_frequency=0.5): """ 显式等待指定元素出现,存在返回该元素,不存在抛timeout """ # 显式等待,超时抛错 WebDriverWait(self.driver, timeout, poll_frequency).until(ec.visibility_of_element_located(loc)) # 找到,返回元素 return ec._element_if_visible(ec._find_element(self.driver, loc))
3.获取toast文案
def get_toast_text(self, toast_message=(By.XPATH, '//*[contains(@text ,\'未发现"QQ客户端"\')]')): """ 获取toast提示文案 """ # 获取toast提示内容 qq_toast_element = WebDriverWait(self.driver, 5).until(lambda x: x.find_element(*toast_message)) return {'toast': {'text': qq_toast_element.text, 'element': qq_toast_element}}
4.拖拽某元素到指定位置
def click_and_hold_element_to_xyoffset(self, el, x_offset, y_offset): """ 长按某元素,拖拽一定偏移量,location获取的是元素矩形左上角坐标,如悬浮球执行 click_and_hold_element_to_xyoffset(el, -200, -500)后坐标变化{'x': 870, 'y': 1800} => {'x': 870, 'y': 1300},悬浮球 自动靠边,x坐标不变 """ # 操作链,session actions = ActionChains(self.driver) # 移动至指定元素 actions.move_to_element(el) # 长按 actions.click_and_hold() # 相对该元素的偏移量,如想左移动200向上移动500 =>(-200, -500) actions.move_by_offset(x_offset, y_offset) # 释放鼠标 actions.release() # 执行操作链 actions.perform() # 链式调用 return self
5.软键盘重写
def ime_actions_by_att(self, att): """ 软键盘操作,重写Enter键完成搜索、完成等操作 normal, unspecified, none, go, search, send, next, done, previous search 搜索;send 发送 """ self.driver.execute_script('mobile: performEditorAction', {'action': att}) return self
多设备并行
# 多进程中,同一个变量,各自有一份拷贝存在于每个进程中, 互不影响; # 多线程中,所有变量都由所有线程共享,任何一个变量都可以被任何一个线程修改. devices_pool = [] for tmp_udid in ConfigData().mobile_data().keys(): devices_pool.append(multiprocessing.Process(target=run_testcase, args=(tmp_udid,))) for devices_udid in devices_pool: devices_udid.start() for devices_udid in devices_pool: devices_udid.join()