移动端自动化测试系列之四——生成定位元素

优雅的生成定位元素

Posted by Mio4kon on 2017-04-13

前言

之所以把定位元素单独拎出来说,是因为我觉得在写移动端测试框架的时候,如果处理不好的话,元素的定位是比较麻烦的事情.

如果对 Appium 稍微了解的童鞋一定知道定位元素的方式有很多种:

  • id
  • name
  • xpath
  • tag_name

这么多的查找方式如果都写在代码中如下:

1
2
3
4
5
find_elements_by_id(R.id.login)
find_elements_by_name('登录')
find_elements_by_xpath('//android.support.v7.widget.RecyclerView')
....
# 甚至还有查单个元素的find_element_by_*的方法

如果都写在代码会有什么结果?

  1. 不直观,不利于查找
  2. 如果页面元素发生变动,比如id突然变化.但是整体case没有任何改变.我们还需要去改代码.

那么如何去解决这两个痛点,就是这篇教程的主要目的,在说到解决痛点之前,我先简单介绍几款小框架,在最后会说明为什么结合了这几款小框架就能够解决这两个痛点.如果对着几个小框架毕竟熟悉,可以直接看最后一小节.

PyYAML

安装

pip3 install PyYAML

用于解析 yaml 文件

使用方法非常简单:

1
2
3
4
def parse():
L.i('解析page.yaml, Path:' + pages_path)
with open(pages_path, 'r', encoding='utf-8') as f:
return yaml.safe_load(f)

这样就可以把 yaml 文件的内容解析成一个对象

watchdog

安装

pip3 install watchdog

用于监听某文件是否发生变化,一旦发生变化(保存,删除等)既执行回掉.

先写一个Handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class WatchHandler(PatternMatchingEventHandler):
# 监听文件类型
patterns = ["*.yaml"]
# 想要监听的文件路径
watch_path = "/Users/mio4kon/.../pages.yaml"
def on_created(self, event):
# 比对看看是否真的是想要监听的文件
if self.watch_path == event.src_path:
L.i('监听到文件发生了变化')
try:
gen_page_py()
except Exception as e:
pass

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
if __name__ == "__main__":
event_handler = WatchHandler()
full_path = event_handler.watch_path
path = full_path[:full_path.rfind('/') + 1]
observer = Observer()
observer.schedule(event_handler, path)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()

这样的话每当pages.yaml文件发生变化都会执行我定义的gen_page_py()方法.

这些是干什么的用的呢?后面会说到.现在只需要知道 watchdog 能做什么即可.

Jinja2

安装

pip3 install Jinja2

用于生成模板代码.

使用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@staticmethod
def gen_page_py():
"""
利用jinja2生成pages.py文件
"""
base_dir = Config.BASE_PATH_DIR
template_loader = jinja2.FileSystemLoader(searchpath=base_dir+"/page/template")
template_env = jinja2.Environment(loader=template_loader)
page_list = GenPages.gen_page_list()
_templateVars = {
'page_list': page_list
}
template = template_env.get_template("pages")
with open(base_dir+'/page/pages.py', 'w', encoding='utf-8') as f:
f.write(template.render(_templateVars))

效果

之所以要用到上面这三个框架.目的是为了将元素定位简单化.并将定位的方式从代码中抽离.方便查找以及修改用例

之前说的两个痛点,我在最初学习 Appium 的时候就深有体会,于是我搜寻了很多相关的测试框架,最终找到一种我认为比较科学的解决方式,其实这个解决方式还是之前在写java测试框架时看过的某一款框架(patatiumAppUi)中用到的方式,不过其作者使用的是xml来定位元素,而且在使用方式上也略微麻烦一点,如果你还有更好的想法,希望能分享出来.

总之通过上述三个框架组合最终不仅解决了上面两个痛点,而且非常易于添加新的元素查找.具体使用方式如下.

开启文件监听

执行项目中的 watch_dog.py

python3 watch_dog.py

定位元素

打开在项目中的pages.yaml文件写入如下内容:

1
2
3
4
5
6
7
8
9
---
LoginPage:
dec: 登录页面
locators:
-
name: 注册
timeOutInSeconds: 20
type: name
value: 注册

保存该文件

至此,文件定位已经完成了.剩下要做的就是在case中用到这个定位的元素了.

使用元素

使用元素也很简单,下面是点击元素的方法:

action.click(LoginPage.登录)

yaml配置说明

  • LoginPage : 主要标识元素所属页面
  • dec:描述页面,可以省略
  • locators - name: 定位元素的名称
  • locators - timeOutInSeconds: 超时时间,重试查找的时间,省略后默认是20秒
  • locators - type: 定位元素方式
  • locators - value:定位元素的值

参考链接

http://pyyaml.org/wiki/PyYAMLDocumentation

https://pypi.python.org/pypi/watchdog

http://jinja.pocoo.org/docs/2.9/

https://testerhome.com/topics/6798