前言
bok choy是一個開源的使用python語言,以Page Object模式封裝selenium的驗(yàn)收測試框架。在工作中可以用它來做UI層面的自動化。為了更好地理解本文,您需要有selenium和python的基礎(chǔ)知識。
準(zhǔn)備工作
需要安裝python和pip
使用pip安裝即可。
pip install bok_choy
寫Page
PO設(shè)計(jì)模式中是以頁面(page)為一個單位,作為一個對象。將這個頁面所做的動作作為這個頁面對象的方法(比如點(diǎn)擊某個按鈕,在某個輸入框輸入文字等操作),在具體寫用例的時候都是實(shí)例化頁面對象,調(diào)用該對象的相應(yīng)方法,這樣寫的好處是:如果某個頁面進(jìn)行了改版,頁面元素發(fā)生了改變,對測試用例是沒有影響的,只要在相應(yīng)的Page object里修改相應(yīng)方法就好了。
寫Pages前需要分析測試場景,以測試百度搜索為例,首先需要在百度搜索頁面輸入關(guān)鍵字,并點(diǎn)擊搜索按鈕。然后頁面會跳轉(zhuǎn)到一個搜索結(jié)果頁,我們驗(yàn)證結(jié)果頁是否包含關(guān)鍵字即可。在這個場景中,我們涉及到了兩個頁面,一個是搜索首頁,一個是搜索結(jié)果頁,我們新建一個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賦值,還要實(shí)現(xiàn)is_browser_on_page方法。
url是這個頁面的入口,在測試過程中,會遇到一種情況是你不關(guān)心它的url具體是多少,因?yàn)檫@個頁面總是從別的頁面點(diǎn)擊進(jìn)入的,而不是直接從瀏覽器輸入url進(jìn)入,這時,將它的url設(shè)為None即可,上例中的BaiduSearchResultPage(搜索結(jié)果頁)就是這種情況。
is_browser_on_page方法,是PageObject類的抽象方法,需要在子類中具體實(shí)現(xiàn)。這個方法的作用主要是判斷瀏覽器打開的是不是你要的這個頁面。在百度搜索頁這個實(shí)例中,為了確保搜索首頁打開并加載完成了,我用了搜索按鈕是否存在來判斷。而對于搜索結(jié)果頁,必須有測試結(jié)果在頁面展示出來,才能說明這個頁面完全打開了,所以用測試結(jié)果元素是否存在來判斷。
bok-choy中提供兩種定位方式:css和xpath,本例中使用css定位。
self.q(css='#su')
除了url和is_browser_on_page是每個頁面對象都有的,其他方法需要根據(jù)具體頁面上的元素和操作來增加。
BaiduSearchPage-百度搜索首頁,在這個頁面我們需要做的操作有1.在輸入框輸入文字,所以我們寫了input_search_key方法;2.點(diǎn)擊搜索按鈕,所以我們寫了click_search_btn方法,從方法的命名上我們也能看出來這兩個方法是什么作用。一個完整的搜索動作,包含了這兩個步驟,所以又寫了一個search方法。頁面中的各種操作方法相當(dāng)于一塊一塊的拼圖,具體想拼成什么樣,根據(jù)不同測試場景可以自由地組合。目前頁面中的search方法算是兩個小拼圖拼出的一個場景。在百度的首頁,還可以點(diǎn)擊貼吧、圖片等,這些操作也可以寫到這個頁面對象中,以備其他測試場景使用。
BaiduSearchResultPage-搜索結(jié)果頁,這個頁面是在搜索頁點(diǎn)搜索按鈕之后,跳轉(zhuǎn)進(jìn)入的。進(jìn)入這個頁面后,主要是需要驗(yàn)證搜索結(jié)果中包含搜索關(guān)鍵字。因而有了search_results來返回搜索第一個結(jié)果的文字,以便于在測試中去使用。這個方法加了property裝飾器,區(qū)別將在下一部分展示。
寫測試用例
有了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"學(xué)堂在線"
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默認(rèn)是使用firefox運(yùn)行測試用例,它支持的瀏覽器有火狐、chrome、IE、safari和phantomjs。如果想要修改運(yùn)行測試的瀏覽器,需要修改一下環(huán)境變量SELENIUM_BROWSER即可。本例中,我們將運(yùn)行測試的瀏覽器換成了chrome。其他有效值有'firefox', 'internet explorer', 'safari'和 'phantomjs',使用非火狐瀏覽器記得下載相應(yīng)的Webdriver,將webdriver放到與測試相同的文件夾下即可。
在測試文件中,首先需要實(shí)例化頁面對象
self.baidu_search_page = BaiduSearchPage(self.browser)
然后就可以調(diào)用該頁面對象的方法
self.baidu_search_page.visit().search(test_key)
請注意,在調(diào)用操作方法的時候先調(diào)用了visit(),visit方法通過在頁面對象中定義的url打開頁面。在頁面中做的任何操作,前提都是該頁面被正確地打開了,所以每次調(diào)用都應(yīng)該先調(diào)visit()。
但是,我們注意到在取搜索結(jié)果的時候并沒有調(diào)用visit,代碼如下:
self.baidu_results_page.search_results
這是因?yàn)樵趯憇earch_results時,我們加上了裝飾器property,那它就變成對象的屬性了,可以直接用“點(diǎn)”訪問到。
最后我們用assert 對測試結(jié)果進(jìn)行驗(yàn)證。
運(yùn)行測試
代碼已寫完,現(xiàn)在可以跑測試(≧≦)/啦! 運(yùn)行結(jié)果如下。

在測試的過程中,如果測試用例沒有pass,框架會自動默認(rèn)在跑測試的路徑下保存截圖和日志,如果你想把他們保存在別的地方,可修改環(huán)境變量SCREENSHOT_DIR和SELENIUM_DRIVER_LOG_DIR。
bok-choy的基本使用就是如此,你學(xué)會了嗎?想了解更多可訪問官方文檔(見參考文獻(xiàn))哦~
以上示例代碼可在github查看