1.异常优化
考虑以下情形。
deftestLogin(): #从Excel文件中读入测试数据,比如:Jerry/123456 #继续后续测试 defteardown(): #从数据库表中删除的读入的数据,比如:Jerry/123456 ...
比如测试程序在继续后续测试的时候出现了一个异常,比如元素没有找到,系统会自动退出,而不去执行teardown方法,也就是说数据库中的数据没有得到清除,这样如果下一次仍旧执行这个测试用例,这样就会产生异常,这个异常是刚才没有执行清除数据造成,这时的数据就叫做“脏数据”,为了解决这个问题,可以通过使用Python的try-except来捕获异常,并且将所有的方法封装在一个类中。在util.py中封装一个class类。
1)封装定位API
案例:封装定位API。 deffind_element_by_id(self,driver,mystr): try: return driver.find_element_by_id(mystr) exceptNoSuchElementException: print("find_element_by_id 没有发现元素"+mystr)
这样如果系统通过by_id方式找不到某个元素,测试程序会抛出“find_element_by_id 没有发现元素"+mystr(mystr即定位的id号)”信息,然后继续下面的程序。调用的时候采用下面的方法。
defsetUp(self): d = drivers() self.driver=d.driver self.fd=findby() self.fd.implicitly_wait(self.driver,5) … deftest_XXX(): self.fd.find_element_by_id(self.driver,"kw").clear()
其他的定位方式也采取同样的方法。
2)封装操作API
案例:封装操作API。
defsend_keys(self,elenment,send_string): try: elenment.send_keys(send_string) except: print("send_keys操作失败")
当执行send_keys发生异常,系统抛出“send_keys操作失败”信息,然后继续下面的程序。调用的时候采用下面的方法。
self.fd.send_keys(self.fd.find_element_by_id(self.driver,"kw"),inputstring)
2.Retry优化
UI自动化测试程序的最大问题之一在于由于网络的不稳定,从而造成页面元素不是不存在,而是还没有被调出来(虽然Selenium提供了显隐式等待,实际工程中会发现这两个方法是有缺陷的,并且好些浏览器根本就不支持)。在这里进行如下的优化。
案例:Retry优化。
deffind_element_by_id(self,driver,mystr): try: return driver.find_element_by_id(mystr) except NoSuchElementException: for i in range(2): try: time.sleep(2000) return driver.find_element_by_id(mystr) except NoSuchElementException: print("尝试第"+str(i+1)+"次失败") print("尝试第3次失败") print("find_element_by_id 没有发现元素"+mystr)
当程序找不到元素的时候,等待2秒钟,继续获取,如果还是没有取到,继续等待,在这里设置了3次的等待机会,如果没有,则报异常信息。
3.对页面的封装
案例:测试添加用户购物配送地址功能。
deftest_Add_Addess(self): username='cindy' password='123456' #登录 self.clear(self.find_element_by_id(driver,"id_username")) self.send_keys(self.find_element_by_id(driver,"id_username"),username) self.clear(self.find_element_by_id(driver,"id_password")) self.send_keys(self.find_element_by_id(driver,"id_password"),password) self.submit(self.find_element_by_class_name(driver,"form-signin")) #在登录首页找到用户名 self.fd.click(self.fd.find_element_by_link_text(self.driver,username)) #进入用户信息列表 self.fd.click(self.fd.find_element_by_id(self.driver,"add_address")) #进入添加送货地址信息页面,添加收货信息 self.fd.clear(self.fd.find_element_by_name(self.driver,"address")) self.fd.send_keys(self.fd.find_element_by_name(self.driver,"address"),"北京清华") self.fd.clear(self.fd.find_element_by_name(self.driver,"phone")) self.fd.send_keys(self.fd.find_element_by_name(self.driver,"phone"),"13699876655") self.fd.click(self.fd.find_element_by_xpath(self.driver,"/html/body/div/form/button")) #验证加入的信息 self.assertIsNotNone(self.fd.find_element_by_link_text(self.driver,"删除")) #测试完毕,清场操作 self.fd.click(self.fd.find_element_by_link_text(self.driver,"删除"))
被测对象是一个附录A电子商务网站,要测试在用户界面添加一条收货信息。必须先登录,登录完毕后点击当前用户名的超链接,然后进入用户信息界面,接下来点击新建用户收货地址按钮,进入新建页面,建立完毕进行断言,最后为了以后仍旧可以进行这个测试用例,进行清除操作。由此可见,如果一个测试业务比较长,按照这样的写法可读性是比较差的,并不便于维护,因此采用目前比较流行的基于页面的封装方法。
先对登录页面进行封装,代码如下。
#通用信息 classUtil: def __init__(self,driver): self.driver = driver def logout(self): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"退出")) findby.quit(self,self.driver) #登录页面 class LoginPage: def __init__(self,driver): self.driver = driver #登录操作 def login(self,username,password): findby.clear(self.driver,findby.find_element_by_id(self,self.driver,"id_username")) #清空用户输入框 findby.send_keys(self.driver,findby.find_element_by_id(self,self.driver,"id_username"),username) #输入用户名 findby.clear(self.driver,findby.find_element_by_id(self,self.driver,"id_password")) #清空密码输入框 findby.send_keys(self.driver,findby.find_element_by_id(self,self.driver,"id_password"),password)# 输入密码 findby.submit(self.driver,findby.find_element_by_class_name(self,self.driver,"form-signin")) #提交表单
产品页面封装如下。
#产品页面 classProductPage: def __init__(self,driver): self.driver = driver #进入用户信息页面 def click_username(self,username): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,username)) #点击登录用户名链接
用户详情页面封装如下。
#用户详情页面 classUserPage: def __init__(self,driver): self.driver = driver #添加购物配送地址信息 def click_add_address_button(self): findby.click(self.driver,findby.find_element_by_id(self,self.driver,"add_address")) #验证地址信息 def check_address(self): returnfindby.find_element_by_link_text(self,self.driver,"删除") #删除地址信息 def delete_address(self): delete_button = findby.find_element_by_link_text(self,self.driver,"删除") findby.click(self.driver,delete_button) 添加地址页面封装如下。 #地址 classAddressPage: def __init__(self,driver): self.driver = driver #添加新地址 defcreate_address(self,addess,phone): findby.clear(self.driver,findby.find_element_by_name(self,self.driver,"address")) #清空地址栏 findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"address"),addess) #输入地址信息 findby.clear(self.driver,findby.find_element_by_name(self,self.driver,"phone")) #清空电话栏 findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"phone"),phone) #输入电话信息 findby.submit(self.driver,findby.find_element_by_xpath(self,self.driver,"/html/body/div/form/button")) #提交表单 这样,验证添加购物地址的测试代码如下。 #coding:utf-8 fromselenium import webdriver fromselenium.webdriver.support.ui import WebDriverWait importunittest,time fromutil import drivers,findby frompage import Util,LoginPage,ProductPage,UserPage,AddressPage,CartPage classCheckEBusiness(unittest.TestCase): def setUp(self): driver = drivers().driver fd = findby() self.util = Util(driver) self.loginpage = LoginPage(driver) self.producepage = ProductPage(driver) self.userpage = UserPage(driver) self.addresspage = AddressPage(driver) self.cartpage = CartPage(driver) fd.implicitly_wait(driver,5) fd.get(driver,"http://127.0.0.1:8000") self.username = "cindy" self.password = "123456" self.adddress = "首体南路3号" self.phone = "13681732596" deftest_Add_Addess(self): self.loginpage.login(self.username,self.password) self.producepage.click_username(self.username) self.userpage.click_add_address_button() self.addresspage.create_address(self.adddress,self.phone) self.assertIsNotNone(self,self.userpage.check_address()) self.userpage.delete_address() if __name__=="__main__": unittest.main()
- 这样测试程序的代码可读性与可维护性都得到了很好的加强。接下来添加测试“购物车功能”的验证。只需在Product类中建立如下两个方法。
案例:测试添加商品进购物车功能。
#放入购物车 defput_into_cart(self): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"放入"))# 点击“放入”链接 #查看购物车 defview_cart(self): findby.click(self.driver,findby.find_element_by_partial_link_text(self,self.driver,"查看购物车"))# 点击“查看购物车”链接在加入一个Cart(购物车)类。 然后增加一个购物车的类。 #购物车页面 classCartPage: def __init__(self,driver): self.driver = driver #验证购物车中是否存在商品 def check_goods(self): returnfindby.find_element_by_xpath(self,self.driver,"//*[@id=\"id_count\"]") #删除购物车中总的商品 def delete_goods(self): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"移除")) 相应的测试代码如下。 deftest_Add_Goods_into_Cart(self): self.loginpage.login(self.username,self.password) self.producepage.put_into_cart() self.producepage.view_cart() self.assertIsNotNone(self.cartpage.check_goods()) self.cartpage.delete_goods()
最后再来验证一下对商品查询的功能,在Product类中加入。
案例:测试商品查询功能。
#商品查询 defsearch_goods(self,good_name): findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"good"),good_name)#输入查询内容 findby.click(self.driver,findby.find_element_by_xpath(self,self.driver,"//*[@id=\"navbar\"]/form/button"))#输入查询内容 returnfindby.find_element_by_link_text(self,self.driver,"放入") 在测试代码中加入如下两行测试语句就可以了。 deftest_Search_Goods(self): self.loginpage.login(self.username,self.password) self.assertIsNotNone(self.producepage.search_goods("茶"))
案例:使用Pytest测试电子商务网站
现在用Pytest+allure完成前面几个测试用例,代码如下。
page.py
#!/usr/bin/envpython #coding:utf-8 fromselenium import webdriver from selenium.common.exceptionsimport NoSuchElementException fromselenium.webdriver.support.ui import WebDriverWait fromselenium.webdriver.common.by import By fromselenium.webdriver import ActionChains fromutil import findby importtime importallure #通用信息 classUtil: def __init__(self,driver): self.driver = driver def logout(self): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"退出")) findby.quit(self,self.driver) #登录页面 classLoginPage: def __init__(self,driver): self.driver = driver @allure.step("登录系统") def login(self,username,password): findby.clear(self.driver,findby.find_element_by_id(self,self.driver,"id_username"))#清空用户输入框 findby.send_keys(self.driver,findby.find_element_by_id(self,self.driver,"id_username"),username)#输入用户名 findby.clear(self.driver,findby.find_element_by_id(self,self.driver,"id_password"))#清空密码输入框 findby.send_keys(self.driver,findby.find_element_by_id(self,self.driver,"id_password"),password)#输入密码 findby.submit(self.driver,findby.find_element_by_class_name(self,self.driver,"form-signin"))#提交表单 #产品页面 classProductPage: def __init__(self,driver): self.driver = driver @allure.step("进入用户信息页面") def click_username(self,username): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,username))#点击登录用户名链接 @allure.step("放入购物车") def put_into_cart(self): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"放入"))# 点击“放入”链接 @allure.step("查看购物车") def view_cart(self): findby.click(self.driver,findby.find_element_by_partial_link_text(self,self.driver,"查看购物车"))# 点击“查看购物车”链接 @allure.step("商品查询") def search_goods(self,good_name): findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"good"),good_name)#输入查询内容 findby.click(self.driver,findby.find_element_by_xpath(self,self.driver,"//*[@id=\"navbar\"]/form/button"))#输入查询内容 return findby.find_element_by_link_text(self,self.driver,"放入") #购物车页面 classCartPage: def __init__(self,driver): self.driver = driver @allure.step("验证购物车中是否存在商品") def check_goods(self): returnfindby.find_element_by_xpath(self,self.driver,"//*[@id=\"id_count\"]") @allure.step("删除购物车中总的商品") def delete_goods(self): findby.click(self.driver,findby.find_element_by_link_text(self,self.driver,"移除")) #登录用户详情页面 classUserPage: def __init__(self,driver): self.driver = driver @allure.step("添加购物配送地址信息") def click_add_address_button(self): findby.click(self.driver,findby.find_element_by_id(self,self.driver,"add_address")) @allure.step("验证地址信息") def check_address(self): returnfindby.find_element_by_link_text(self,self.driver,"删除") @allure.step("删除地址信息") def delete_address(self): delete_button =findby.find_element_by_link_text(self,self.driver,"删除") findby.click(self.driver,delete_button) #地址 classAddressPage: def __init__(self,driver): self.driver = driver @allure.step("添加新地址") def create_address(self,addess,phone): findby.clear(self.driver,findby.find_element_by_name(self,self.driver,"address"))#清空地址栏 findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"address"),addess)#输入地址信息 findby.clear(self.driver,findby.find_element_by_name(self,self.driver,"phone"))##清空电话栏 findby.send_keys(self.driver,findby.find_element_by_name(self,self.driver,"phone"),phone)#输入电话信息 findby.submit(self.driver,findby.find_element_by_xpath(self,self.driver,"/html/body/div/form/button"))#提交表单
test_PageObjetTest.py
#!/usr/bin/envpython #coding:utf-8 fromselenium import webdriver fromselenium.webdriver.support.ui import WebDriverWait importtime fromutil import drivers,findby frompage import Util,LoginPage,ProductPage,UserPage,AddressPage,CartPage importpytest importallure classTestEBusiness: def setup(self): driver = drivers().driver fd = findby() self.util = Util(driver) self.loginpage = LoginPage(driver) self.producepage = ProductPage(driver) self.userpage = UserPage(driver) self.addresspage = AddressPage(driver) self.cartpage = CartPage(driver) fd.implicitly_wait(driver,5) fd.get(driver,"http://127.0.0.1:8000") self.username = "cindy" self.password = "123456" self.adddress = "首体南路3号" self.phone = "13681732596" @allure.feature('电子商务产品') @allure.story('添加配货地址') @allure.severity('Normal') @allure.issue("http://www.jila.com") @allure.testcase("http://www.testlink.com") def test_Add_Addess(self): self.loginpage.login(self.username,self.password) self.producepage.click_username(self.username) self.userpage.click_add_address_button() self.addresspage.create_address(self.adddress,self.phone) try: self.userpage.check_address() assert 1==1 except: assert 0==1 self.userpage.delete_address() @allure.feature('电子商务产品') @allure.story('添加进购物车') @allure.severity('Normal') @allure.issue("http://www.jila.com") @allure.testcase("http://www.testlink.com") def test_Add_Goods_into_Cart(self): self.loginpage.login(self.username,self.password) self.producepage.put_into_cart() self.producepage.view_cart() try: self.cartpage.check_goods() assert 1==1 except: assert 0==1 self.cartpage.delete_goods() @allure.feature('电子商务产品') @allure.story('模糊查询商品') @allure.severity('Normal') @allure.issue("http://www.jila.com") @allure.testcase("http://www.testlink.com") def test_Search_Goods(self): self.loginpage.login(self.username,self.password) try: self.producepage.search_goods("茶") assert 1==1 except: assert 0==1 def teardown(self): self.util.logout() if__name__ == '__main__': pytest.main(['-sv', '-q', '--alluredir','./report/xml'])
建立文件report.bat。
del.\report\* pytest.\test_PageObjetTest.py -s -q --alluredir report .\report\ allureserve .\report allureopen -h 127.0.0.1 -p 8083 .\report\report\
运行后产生如图1所示的测试报告。
图1 电子商务网站Pytest+Selenium 测试报告
顾老师性能测试课程
selenium自动化测试
https://study.163.com/course/courseMain.htm?courseId=1209835807&share=2&shareId=480000002205486