前言
bok choy是一个开源的使用python语言,以Page Object模式封装selenium的验收测试框架。在工作中可以用它来做UI层面的自动化。为了更好地理解本文,您需要有selenium和python的基础知识。
准备工作
需要安装python和pip
使用pip安装即可。
pip install bok_choy
写Page
PO设计模式中是以页面(page)为一个单位,作为一个对象。将这个页面所做的动作作为这个页面对象的方法(比如点击某个按钮,在某个输入框输入文字等操作),在具体写用例的时候都是实例化页面对象,调用该对象的相应方法,这样写的好处是:如果某个页面进行了改版,页面元素发生了改变,对测试用例是没有影响的,只要在相应的Page object里修改相应方法就好了。
写Pages前需要分析测试场景,以测试百度搜索为例,首先需要在百度搜索页面输入关键字,并点击搜索按钮。然后页面会跳转到一个搜索结果页,我们验证结果页是否包含关键字即可。在这个场景中,我们涉及到了两个页面,一个是搜索首页,一个是搜索结果页,我们新建一个pages.py文件,见下面的代码。
# -*- coding: utf-8 -*-
from bok_choy.page_object import PageObject
class BaiduSearchPage(PageObject):
"""
Baidu search page
"""
url = 'https://www.baidu.com/'
def is_browser_on_page(self):
return self.q(css='#su').is_present()
def input_search_key(self, keyword):
return self.q(css="#kw").fill(keyword)
def click_search_btn(self):
self.q(css="#su").click()
def search(self, keyword):
self.input_search_key(keyword)
self.click_search_btn()
BaiduSearchResultPage(self.browser).wait_for_page()
class BaiduSearchResultPage(PageObject):
"""
Baidu search result page
"""
url = None
def is_browser_on_page(self):
return self.q(css='h3').is_present()
@property
def search_results(self):
return self.q(css='h3').first.text
如上述代码所示,自己写的页面对象都继承于bokchoy的PageObject,每个页面对象都必须给url赋值,还要实现is_browser_on_page方法。
url是这个页面的入口,在测试过程中,会遇到一种情况是你不关心它的url具体是多少,因为这个页面总是从别的页面点击进入的,而不是直接从浏览器输入url进入,这时,将它的url设为None即可,上例中的BaiduSearchResultPage(搜索结果页)就是这种情况。
is_browser_on_page方法,是PageObject类的抽象方法,需要在子类中具体实现。这个方法的作用主要是判断浏览器打开的是不是你要的这个页面。在百度搜索页这个实例中,为了确保搜索首页打开并加载完成了,我用了搜索按钮是否存在来判断。而对于搜索结果页,必须有测试结果在页面展示出来,才能说明这个页面完全打开了,所以用测试结果元素是否存在来判断。
bok-choy中提供两种定位方式:css和xpath,本例中使用css定位。
self.q(css='#su')
除了url和is_browser_on_page是每个页面对象都有的,其他方法需要根据具体页面上的元素和操作来增加。
BaiduSearchPage-百度搜索首页,在这个页面我们需要做的操作有1.在输入框输入文字,所以我们写了input_search_key方法;2.点击搜索按钮,所以我们写了click_search_btn方法,从方法的命名上我们也能看出来这两个方法是什么作用。一个完整的搜索动作,包含了这两个步骤,所以又写了一个search方法。页面中的各种操作方法相当于一块一块的拼图,具体想拼成什么样,根据不同测试场景可以自由地组合。目前页面中的search方法算是两个小拼图拼出的一个场景。在百度的首页,还可以点击贴吧、图片等,这些操作也可以写到这个页面对象中,以备其他测试场景使用。
BaiduSearchResultPage-搜索结果页,这个页面是在搜索页点搜索按钮之后,跳转进入的。进入这个页面后,主要是需要验证搜索结果中包含搜索关键字。因而有了search_results来返回搜索第一个结果的文字,以便于在测试中去使用。这个方法加了property装饰器,区别将在下一部分展示。
写测试用例
有了pages.py之后,就可以写用例啦,建立test_search.py文件。
# -*- coding: utf-8 -*-
import os
import unittest
from bok_choy.web_app_test import WebAppTest
from pages import BaiduSearchPage, BaiduSearchResultPage
class TestBaidu(WebAppTest):
"""
Tests for the Baidu site.
"""
def setUp(self):
"""
Instantiate the page object.
"""
super(TestBaidu, self).setUp()
self.baidu_search_page = BaiduSearchPage(self.browser)
def test_page_existence(self):
"""
Make sure that the page is accessible.
"""
self.baidu_search_page.visit()
def test_search(self):
test_key = u"学堂在线"
self.baidu_search_page.visit().search(test_key)
self.baidu_results_page = BaiduSearchResultPage(self.browser)
result = self.baidu_results_page.search_results
assert test_key in result[0]
if __name__ == '__main__':
os.environ["SELENIUM_BROWSER"] = "chrome"
unittest.main()
bok-choy默认是使用firefox运行测试用例,它支持的浏览器有火狐、chrome、IE、safari和phantomjs。如果想要修改运行测试的浏览器,需要修改一下环境变量SELENIUM_BROWSER即可。本例中,我们将运行测试的浏览器换成了chrome。其他有效值有'firefox', 'internet explorer', 'safari'和 'phantomjs',使用非火狐浏览器记得下载相应的Webdriver,将webdriver放到与测试相同的文件夹下即可。
在测试文件中,首先需要实例化页面对象
self.baidu_search_page = BaiduSearchPage(self.browser)
然后就可以调用该页面对象的方法
self.baidu_search_page.visit().search(test_key)
请注意,在调用操作方法的时候先调用了visit(),visit方法通过在页面对象中定义的url打开页面。在页面中做的任何操作,前提都是该页面被正确地打开了,所以每次调用都应该先调visit()。
但是,我们注意到在取搜索结果的时候并没有调用visit,代码如下:
self.baidu_results_page.search_results
这是因为在写search_results时,我们加上了装饰器property,那它就变成对象的属性了,可以直接用“点”访问到。
最后我们用assert 对测试结果进行验证。
运行测试
代码已写完,现在可以跑测试(≧≦)/啦! 运行结果如下。
在测试的过程中,如果测试用例没有pass,框架会自动默认在跑测试的路径下保存截图和日志,如果你想把他们保存在别的地方,可修改环境变量SCREENSHOT_DIR和SELENIUM_DRIVER_LOG_DIR。
bok-choy的基本使用就是如此,你学会了吗?想了解更多可访问官方文档(见参考文献)哦~
以上示例代码可在github查看