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)