web自動化的測試最大的挑戰之一也許就是隨着項目的進展,項目在不停的變化,測試這邊也得跟着項目變化來保障項目的順利進展,在現實的軟件項目中,變化是一個常數,而我們只有適應變化,纔可以把握變化,但是自動化這邊必須要考慮的一個現實問題就是,如何可以更加高效的提高代碼的維護量,如何更加完美的來重構編寫的代碼?另外需要考慮的是,在一個現實的項目中,不管需求是多麼的變化,編寫的自動化的case以及這些case的代碼量多麼多,在一個敏捷的項目中,需要在一個版本提交測試後,測試這邊務必在有限的時間內給出測試報告,這期間,就包含了自動化的執行,自動化的測試報告以及自動化執行後,對錯誤的分析(可能是代碼錯誤?可能是功能錯誤?),和某些需求變化後,對自動化代碼的重構,很顯然,使用以前的方式很難解決這樣的一個現實問題。
解決如上問題是辦法是我們利用pageobject,這樣我們可以對我們的代碼得到控制,可以表達對功能的測試以及方法可複用的功能。PageObject對象表示區域中的web應用程序用戶界面測試。這減少了重複代碼,意味着,如果用戶界面發生改變,需要只在一個地方應用修補程序。具體見如下的截圖:
就已百度登錄爲實例,來說明pageobject在項目中的實際用途,我們新建BasePage.py文件,創建類Page,在類中編寫打開瀏覽器方法和定位元素屬性方法,具體代碼如下:
#!/usr/bin/python
#coding:utf-8
fromselenium.webdriver.support.wait import WebDriverWait
fromselenium import webdriver
fromappium import webdriver
import xml.dom.minidom,os,glob
import csv,xlrd,threading,os,sys,chardet
import urllib,urlparse,HTMLParser ,sgmllib
fromtime import sleep
classPage(object):
kb_url=''
def__init__(self,selenium_driver,base_url=kb_url,parent=None):
"""
對objectpage的Page類進行實例化
:param selenium_driver:webdriver
:param base_url:測試的url
:param parent:
:return:
"""
self.base_url=base_url
self.driver=selenium_driver
self.timeout=30
self.parent=parent
self.tabs={}
def _open(self,url):
url=self.base_url+url
self.driver.get(url)
def find_element(self,*loc):
returnself.driver.find_element(*loc)
def open(self):
self._open(self.url)
def on_page(self):
returnself.driver.current_url==(self.base_url+self.url)
編寫登錄的類,登錄的類名稱爲baiduPage.py,該類繼承BasePage,在baiduPage類中編寫元素的屬性以及方法,具體見如下的代碼:
#coding:utf-8
fromselenium import webdriver
importunittest
fromselenium.webdriver.common.by import By
fromtime import sleep
import BasePage
classPage(BasePage.Page,unittest.TestCase):
login_loc=(By.LINK_TEXT,u'登錄')
username_loc=(By.ID,'TANGRAM__PSP_8__userName')
password_loc=(By.ID,'TANGRAM__PSP_8__password')
loginButton_loc=(By.ID,'TANGRAM__PSP_8__submit')
nameText_loc=(By.XPATH,".//*[@id='s_username_top']/span[1]")
#點擊首頁登錄按鈕
def clickLogin(self):
sleep(2)
self.find_element(*self.login_loc).click()
#輸入賬戶
def sendUserName(self,username):
sleep(1)
self.find_element(*self.username_loc).send_keys(username)
#輸入密碼
def sendPasswd(self,password):
sleep(1)
self.find_element(*self.password_loc).send_keys(password)
def send(self,name,passwd):
self.sendUserName(name)
self.sendPasswd(passwd)
def clickLoginButton(self):
self.find_element(*self.loginButton_loc).click()
#獲取用暱稱
def getUserName(self):
returnself.find_element(*self.nameText_loc).text
在如上的代碼中,我們把頁面對象寫在了一個一個文件中,這個文件就是loginPage.py中,同時我們還把頁面操作寫成了一個單獨的方法,這樣可以依次封裝,這樣的目的是即使需求修改,頁面對象被修改,我們只需要修改loginPage.py文件,其他的就不需管,另外一個好處是可以達到測試腳本與頁面對象的分離,見如下的測試文件loginPageTest.py文件的代碼:
#coding:utf-8
fromselenium import webdriver
import unittest
fromtime import sleep
import loginPage
classloginTest(unittest.TestCase):
def setUp(self):
self.driver=webdriver.Firefox()
self.driver.implicitly_wait(30)
self.driver.maximize_window()
self.driver.get('http://www.baidu.com')
def testLogin(self,name='yourname',passwd=your password):
login=loginPage.Page(self.driver)
login.clickLogin()
login.send(name,passwd)
login.clickLoginButton()
self.assertEqual(login.getUserName(),u'清晨無涯')
def tearDown(self):
self.driver.quit()
if__name__=='__main__':
unittest.main(verbosity=2)