🎉 🎂 🍰 TesterHome 创立 6 周年纪念日 🍰 🎂 🎉

Macaca Macaca,通过 content-desc (Android) 等待 / 点击 element,通过 wait_string 判断页面是否达预期

hualin · 2017年03月02日 · 804 次阅读

接上文https://testerhome.com/topics/7658

由于项目特点,无法通过ID/NAME等方式查找element并进行相关操作,但又不想用XPATH(使用XPATH定位使得脚本可读性变低,加之页面布局经常改动,使得使用XPATH的维护量比较大)。因此,写了通用方法(by_accessibility_id)来查找页面element。另外,还写了wait_string的方法来判断页面中是否有特定的字符串。

使用举例:

class MyCarPage(BasePage):
@teststep
def click_add_car(self):
self.click_element_by_accessibility_id('添加车辆')
class InviteFriendsPage(BasePage):
@teststep
def wait_page(self):
if self.wait_string_use_and('福利', '活动规则'):
return True
else:
return False

源码如下:
1、其中的_wait_element是一个通用的内部方法,大家可以用这个方法构造出其他的定位方式,如self._wait_element('content-desc', value=value, max_time=max_time)中,using='content-desc'就是通过'content-desc'查找element。
2、大家有更好的实现方式可以一同讨论

from xml.etree.ElementTree import ElementTree

class BasePage(object):
@classmethod
def set_driver(cls, dri):
cls.driver = dri

def get_driver(self):
return self.driver

def wait_string(self, string, max_time=10):
"""
wait string between the gaven time
:param string: string
:param max_time: time that wait the gaven strings
:return: True or False
"""

times = max_time

for i in range(times):
time.sleep(1)

source = self.driver.source
if string in source:
return True

if i == times - 1:
return False

def wait_string_use_and(self, *args, max_time=10):
"""
wait all strings between the gaven time
:param args: strings
:param max_time: time that wait the gaven strings
:return: True or False
"""

times = max_time

for i in range(10):
time.sleep(1)

source = self.driver.source
previous = False
for j in range(len(args)):
if args[j] in source:
if j != 0 and not previous:
return False

previous = True

if j == len(args) - 1:
return True
else:
if previous:
return False

if i == times - 1:
return False

def wait_string_use_or(self, *args, max_time=10):
"""
wait anyone string between the gaven time
:param args: strings
:param max_time: time that wait the gaven strings
:return: True or False
"""

times = max_time

for i in range(10):
time.sleep(1)

source = self.driver.source
for string in args:
if string in source:
return True

if i == times - 1:
return False

def _find_element_in_nodes(self, nodes, using, value):
for node in nodes:
result = self._find_element_in_node(node, using, value)
if result is not None:
return result

def _find_element_in_node(self, node, using, value):
if node.get(using) == value:
return node

child_nodes = node.findall('node')
if len(child_nodes):
return self._find_element_in_nodes(child_nodes, using, value)
else:
return None

@staticmethod
def _parse_bounds(bounds_str):
bounds = bounds_str.split(',')
x_left = int(bounds[0].strip('['))
y_up = int(bounds[1].split(']')[0])
x_right = int(bounds[1].split(']')[1].strip('['))
y_down = int(bounds[2].strip(']'))

x_center = (x_left + x_right) / 2
y_center = (y_up + y_down) / 2

return x_center, y_center

@staticmethod
def _delete_file(filename):
if os.path.exists(filename):
os.remove(filename)

def _wait_element(self, using, value, max_time=10):
times = max_time

stability_flag = ''
for i in range(times):
time.sleep(1)

file = 'source.xml'
with open(file, 'wt', encoding='utf-8') as f:
f.write(self.driver.source)

try:
tree = ElementTree()
tree.parse(file)
root = tree.getroot()

nodes = root.findall('node')
result = self._find_element_in_nodes(nodes, using, value)
if result is not None:
bounds_str = result.get('bounds')
if stability_flag != bounds_str:
stability_flag = bounds_str
else:
self._delete_file(file)
return result

if i == times - 1:
self._delete_file(file)
return None
except Exception:
self._delete_file(file)
raise Exception

def wait_element_by_accessibility_id(self, value, max_time=10):
"""
wait element by accessibility id. in android, wait content-desc
:param value: value
:param max_time: time that wait the gaven value of accessibility id
:return: True or False
"""

result = self._wait_element('content-desc', value=value, max_time=max_time)
if result is not None:
return True
else:
return False

def click_element_by_accessibility_id(self, value, max_time=10):
"""
click element by accessibility id. in android, wait content-desc
:param value: value
:param max_time: time that wait the gaven value of accessibility id
:return:

raise:
WebDriverException
"""

result = self._wait_element('content-desc', value=value, max_time=max_time)
if result is not None:
x, y = self._parse_bounds(result.get('bounds'))
self._tap(x, y)
else:
raise WebDriverException('No such accessibility id that value was you gaven.')
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 0 条回复 时间 点赞
1楼 已删除
2楼 已删除
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册