Python自動(dòng)化測(cè)試框架之unittest使用詳解
1 unittest框架
unittest 是python 的單元測(cè)試框架,它主要有以下作用:
提供用例組織與執(zhí)行:當(dāng)你的測(cè)試用例只有幾條時(shí),可以不必考慮用例的組織,但是,當(dāng)測(cè)試用例達(dá)到成百上千條時(shí),大量的測(cè)試用例堆砌在一起,就產(chǎn)生了擴(kuò)展性與維護(hù)性等問(wèn)題,此時(shí)需要考慮用例的規(guī)范與組織問(wèn)題了。單元測(cè)試框架就是來(lái)解決這個(gè)問(wèn)題的。
提供豐富的比較方法:在用例執(zhí)行完之后都需要將實(shí)際結(jié)果與預(yù)期結(jié)果進(jìn)行比較(斷言),從而斷定用例是否可以順利通過(guò)。單元測(cè)試一般會(huì)提供豐富的斷言方法。例如,判斷相等/不相等、包含/不包含、True/False等斷言方法。
提供豐富的日志:當(dāng)測(cè)試用例執(zhí)行失敗時(shí)能拋出清晰的失敗原因,當(dāng)所有用例執(zhí)行完成后能提供豐富的執(zhí)行結(jié)果。例如,總的執(zhí)行時(shí)間,失敗用例數(shù),成功用例數(shù)等。
unittest里面有四個(gè)很重要的概念,test fixture,test case,test suite,test runner。
Test Fixture
對(duì)一個(gè)測(cè)試用例環(huán)境的搭建和銷(xiāo)毀,就是一個(gè)fixture,通過(guò)覆蓋setUp()和tearDown()方法來(lái)實(shí)現(xiàn)。
setUp()方法可以進(jìn)行測(cè)試環(huán)境的搭建,比如獲取待測(cè)試瀏覽器的驅(qū)動(dòng),或者如果測(cè)試中需要訪問(wèn)數(shù)據(jù)庫(kù),那么可以在setUp()中通過(guò)建立數(shù)據(jù)庫(kù)連接來(lái)進(jìn)行初始化。
tearDown()方法進(jìn)行環(huán)境的銷(xiāo)毀,可以進(jìn)行關(guān)閉瀏覽器,關(guān)閉數(shù)據(jù)庫(kù)連接,清除數(shù)據(jù)庫(kù)中產(chǎn)生的數(shù)據(jù)等操作;Test Case
一個(gè)TestCase的實(shí)例就是一個(gè)測(cè)試用例。測(cè)試用例就是一個(gè)完整的測(cè)試流程,包括測(cè)試前準(zhǔn)備環(huán)境的搭建(setUp)、實(shí)現(xiàn)測(cè)試過(guò)程的代碼,以及測(cè)試后環(huán)境的還原(tearDown)。單元測(cè)試(unit test)的本質(zhì)就在這里,一個(gè)測(cè)試用例就是一個(gè)完整的測(cè)試單元,可以對(duì)某一個(gè)功能進(jìn)行驗(yàn)證。Test Suite
一個(gè)功能的驗(yàn)證往往需要多個(gè)測(cè)試用例,可以把多個(gè)測(cè)試用例集合在一起執(zhí)行,這個(gè)就產(chǎn)生了測(cè)試套件TestSuite的概念。Test Suit用來(lái)將多個(gè)測(cè)試用例組裝在一起;
Test Runner測(cè)試的執(zhí)行也是非常重要的一個(gè)概念,在unittest框架中,通過(guò)TextTestRunner類(lèi)提供的run()方法來(lái)執(zhí)行test suite/test case。
from selenium import webdriver import unittest import time import os from selenium.common.exceptions import NoAlertPresentException from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.common.by import By class Baidu1(unittest.TestCase): def setUp(self): print("-----setUp-----") self.driver = webdriver.Chrome() self.url = "https://www.baidu.com/" self.driver.maximize_window() time.sleep(3) def tearDown(self): print("-----tearDown-----") self.driver.quit() def test_hao(self): print("111111111") driver = self.driver url = self.url driver.get(url) driver.find_element(By.LINK_TEXT,"hao123").click() time.sleep(6) def test_hbaidu(self): print("22222222") driver = self.driver url = self.url driver.get(url) driver.find_element(By.ID,"kw").send_keys("unittest") driver.find_element(By.ID,"su").submit() time.sleep(5) print(driver.title) # self.assertNotEqual(driver.title, "百度一下_百度搜索", msg="不相等") # self.assertTrue("beautiful"=="beauty", msg="Not Equal!") time.sleep(6) def saveScreenAsPhoto(self, driver, file_name): if not os.path.exists("./image"): os.makedirs("./image") now = time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time())) driver.get_screenshot_as_file("./image/" + now + "-" + file_name) time.sleep(3) print("3333333") if __name__ == "__main__": unittest.main()
這個(gè)腳本中的類(lèi) Baidu1 繼承了unittest.TestCase類(lèi),所以它使用了unittest框架來(lái)組織測(cè)試用例(TestCase)。
setUp() 和 setDown() 是unittest框架中的測(cè)試固件。
以test_開(kāi)頭命名的方法,是測(cè)試方法,在運(yùn)行整個(gè)類(lèi)的時(shí)候會(huì)默認(rèn)執(zhí)行。
unittest提供了全局的main()方法,使用它可以方便地將一個(gè)單元測(cè)試模塊變成可以直接運(yùn)行的測(cè)試腳
本。main()方法搜索所有包含在該模塊中以”test"命名的測(cè)試方法,并自動(dòng)執(zhí)行他們。
2 批量執(zhí)行腳本
2.1 構(gòu)建測(cè)試套件
當(dāng)我們?cè)黾恿吮粶y(cè)試功能和相應(yīng)的測(cè)試用例之后,我們就需要把多個(gè)測(cè)試用例組織在一起執(zhí)行,這就需要用到上文中提到的測(cè)試套件Test Suite
假設(shè)我們已經(jīng)編寫(xiě)了testbaidu1.py,testbaidu2.py兩個(gè)文件
testbaidu2.py
from selenium import webdriver import unittest import time from selenium.common.exceptions import NoAlertPresentException from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.common.by import By class Baidu2 (unittest.TestCase) : def setUp(self): self.driver = webdriver.Chrome() self.driver.implicitly_wait(30) self.base_url = "http://www.baidu.com/" self.driver.maximize_window() self.verificationErrors=[] self.accept_next_alert = True def tearDown(self): self.driver.quit() self.assertEqual([], self.verificationErrors) def test_hao(self): driver = self.driver driver.get(self.base_url) driver.find_element(By.LINK_TEXT,"新聞").click() time.sleep(6) self.assertTrue("123" == "1234", msg="not true") time.sleep(3) def test_baidusearch(self): driver = self.driver driver.get(self.base_url) driver.find_element(By.ID,"kw").clear() driver.find_element(By.ID,"kw").send_keys(u"unittest") driver.find_element(By.ID,"su").click() time.sleep(6) def is_element_present(self, how, what): try: self.driver.find_element(by=how, value=what) except NoSuchElementException as e: return False return True def is_alert_present(self): try: self.driver.switch_to.alert except NoAlertPresentException as e: return False return True def close_alert_and_get_its_text(self): try: alert = self.driver.switch_to.alert alert_text = alert.text if self.accept_next_alert: alert.accept() else: alert.dismiss() return alert_text finally: self.accept_next_alert = True if __name__ == "__main__": unittest.main(verbosity=2)
addTest()
TestSuite類(lèi)的addTest()方法可以把不同的測(cè)試類(lèi)中的測(cè)試方法組裝到測(cè)試套件中,但是addTest()一次只能把一個(gè)類(lèi)里面的一個(gè)測(cè)試方法組裝到測(cè)試套件中。方式如下:
將testbaidu1.py、testbaidu2.py中的測(cè)試方法放到一個(gè)測(cè)試套件中,在testsuite.py中實(shí)現(xiàn)。
testsuite.py
import unittest from testUnittest import testbaidu1 from testUnittest import testbaidu2 def createsuite(): #addTest suite = unittest.TestSuite() suite.addTest(testbaidu1.Baidu1("test_hao")) suite.addTest(testbaidu1.Baidu1("test_hbaidu")) suite.addTest(testbaidu2.Baidu2("test_hao")) suite.addTest(testbaidu2.Baidu2("test_baidusearch")) return suite if __name__=="__main__": suite = createsuite() runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
但是上述做法有兩個(gè)不方便的地方,阻礙腳本的快速執(zhí)行,必須每次修改testsuite.py:
需要導(dǎo)入所有的相關(guān)的py文件,比如 import testbaidu1,每新增一個(gè)腳本就需要導(dǎo)入一個(gè)
addTest一次只能增加一個(gè)測(cè)試方法,如果一個(gè)py文件中有10個(gè)測(cè)試方式,如果都要組裝到測(cè)試套件中,就需要增加10次
makeSuite()和TestLoader()的應(yīng)用
在unittest 框架中提供了makeSuite() 的方法,makeSuite可以實(shí)現(xiàn)把測(cè)試用例類(lèi)內(nèi)所有的測(cè)試case組成的測(cè)試套件TestSuite ,unittest 調(diào)用makeSuite的時(shí)候,只需要把測(cè)試類(lèi)名稱(chēng)傳入即可。
TestLoader 用于創(chuàng)建類(lèi)和模塊的測(cè)試套件,一般的情況下,使TestLoader().loadTestsFromTestCase(TestClass) 來(lái)加載測(cè)試類(lèi)。
runall.py
import unittest,csv import os,sys import time import testbaidu1 import testbaidu2 #手工添加案例到套件, def createsuite(): suite = unittest.TestSuite() #將測(cè)試用例加入到測(cè)試容器(套件)中 suite.addTest(unittest.makeSuite(testbaidu1.Baidu1)) suite.addTest(unittest.makeSuite(testbaidu2.Baidu2)) return suite ''' suite1 = unittest.TestLoader().loadTestsFromTestCase(testbaidu1.Baidu1) suite2 = unittest.TestLoader().loadTestsFromTestCase(testbaidu2.Baidu2) suite = unittest.TestSuite([suite1, suite2]) return suite ''' if __name__=="__main__": suite=createsuite() runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
經(jīng)過(guò)makeSuite()和TestLoader()的引入,我們不用一個(gè)py文件測(cè)試類(lèi),只需要導(dǎo)入一次即可。
discover()的應(yīng)用
discover 是通過(guò)遞歸的方式到其子目錄中從指定的目錄開(kāi)始, 找到所有測(cè)試模塊并返回一個(gè)包含它們對(duì)象的TestSuite ,然后進(jìn)行加載與模式匹配唯一的測(cè)試文件,discover 參數(shù)分別為discover(dir,pattern,top_level_dir=None)
runall.py—注意路徑
import unittest,csv import os,sys import time #手工添加案例到套件, def createsuite(): discover=unittest.defaultTestLoader.discover("../testUnittest",pattern='test*.py',top_level_dir=None) print (discover) return discover if __name__=="__main__": suite=createsuite() runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
2.2 用例的執(zhí)行順序
unittest 框架默認(rèn)加載測(cè)試用例的順序是根據(jù)ASCII 碼的順序,數(shù)字與字母的順序?yàn)椋?0 ~ 9,A ~ Z,a ~ z 。
對(duì)于測(cè)試目錄與測(cè)試文件來(lái)說(shuō), unittest 框架同樣是按照這個(gè)規(guī)則來(lái)加載測(cè)試用例
2.3 忽略用例執(zhí)行
語(yǔ)法:
@unittest.skip(u'The function was canceled, neglects to perform thecase')
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoAlertPresentException import unittest, time, re class Baidu1(unittest.TestCase): #test fixture,初始化環(huán)境 def setUp(self): self.driver = webdriver.Chrome() self.driver.implicitly_wait(30) self.base_url = "http://www.baidu.com/" self.verificationErrors = [] self.accept_next_alert = True @unittest.skip("skipping") def test_baidusearch(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element(By.ID,"kw").click() driver.find_element(By.ID,"kw").clear() driver.find_element(By.ID,"kw").send_keys(u"測(cè)試") driver.find_element(By.ID,"su").click() driver.find_element(By.ID,"su").click() def test_hao(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element(By.LINK_TEXT,"hao123").click() self.assertEqual(u"hao123_上網(wǎng)從這里開(kāi)始", driver.title) #判斷element是否存在,可刪除 def is_element_present(self, how, what): try: self.driver.find_element(by=how, value=what) except NoSuchElementException as e: return False return True #判斷alert是否存在,可刪除 def is_alert_present(self): try: self.driver.switch_to_alert() except NoAlertPresentException as e: return False return True #關(guān)閉alert,可刪除 def close_alert_and_get_its_text(self): try: alert = self.driver.switch_to_alert() alert_text = alert.text if self.accept_next_alert: alert.accept() else: alert.dismiss() return alert_text finally: self.accept_next_alert = True #test fixture,清除環(huán)境 def tearDown(self): self.driver.quit() self.assertEqual([], self.verificationErrors) if __name__ == "__main__": #執(zhí)行用例 unittest.main()
3 unittest斷言
自動(dòng)化的測(cè)試中, 對(duì)于每個(gè)單獨(dú)的case來(lái)說(shuō),一個(gè)case的執(zhí)行結(jié)果中, 必然會(huì)有期望結(jié)果與實(shí)際結(jié)果, 來(lái)判斷該case是通過(guò)還是失敗, 在unittest 的庫(kù)中提供了大量的實(shí)用方法來(lái)檢查預(yù)期值與實(shí)際值, 來(lái)驗(yàn)證case的結(jié)果, 一般來(lái)說(shuō), 檢查條件大體分為等價(jià)性, 邏輯比較以及其他, 如果給定的斷言通過(guò), 測(cè)試會(huì)繼續(xù)執(zhí)行到下一行的代碼, 如果斷言失敗, 對(duì)應(yīng)的case測(cè)試會(huì)立即停止或者生成錯(cuò)誤信息( 一般打印錯(cuò)誤信息即可) ,但是不要影響其他的case執(zhí)行。
unittest 的單元測(cè)試庫(kù)提供了標(biāo)準(zhǔn)的xUnit 斷言方法。下面是一些常用的斷言
斷言方法 | 斷言描述 |
---|---|
assertEqual(arg1, arg2, msg=None) | 驗(yàn)證arg1=arg2,不等則fail |
assertNotEqual(arg1, arg2, msg=None) | 驗(yàn)證arg1 != arg2, 相等則fail |
assertTrue(expr, msg=None) | 驗(yàn)證expr是true,如果為false,則fail |
assertFalse(expr,msg=None) | 驗(yàn)證expr是false,如果為true,則fail |
assertIs(arg1, arg2, msg=None) | 驗(yàn)證arg1、arg2是同一個(gè)對(duì)象,不是則fail |
assertIsNot(arg1, arg2, msg=None) | 驗(yàn)證arg1、arg2不是同一個(gè)對(duì)象,是則fail |
assertIsNone(expr, msg=None) | 驗(yàn)證expr是None,不是則fail |
assertIsNotNone(expr, msg=None) | 驗(yàn)證expr不是None,是則fail |
assertIn(arg1, arg2, msg=None) | 驗(yàn)證arg1是arg2的子串,不是則fail |
assertNotIn(arg1, arg2, msg=None) | 驗(yàn)證arg1不是arg2的子串,是則fail |
assertIsInstance(obj, cls, msg=None) | 驗(yàn)證obj是cls的實(shí)例,不是則fail |
assertNotIsInstance(obj, cls,msg=None) | 驗(yàn)證obj不是cls的實(shí)例,是則fail |
4 HTML報(bào)告生成
腳本執(zhí)行完畢之后,還需要看到HTML報(bào)告,下面我們就通過(guò)HTMLTestRunner.py 來(lái)生成測(cè)試報(bào)告。
修改runall.py
import unittest,csv import os,sys import time import HTMLTestRunner #手工添加案例到套件, def createsuite(): discover=unittest.defaultTestLoader.discover('../testUnittest',pattern='test*.py',top_level_dir=None) print (discover) return discover if __name__=="__main__": curpath=sys.path[0] #取當(dāng)前時(shí)間 now=time.strftime("%Y-%m-%d-%H %M %S",time.localtime(time.time())) if not os.path.exists(curpath+'/resultreport'): os.makedirs(curpath+'/resultreport') filename=curpath+'/resultreport/'+now+'resultreport.html' with open(filename,'wb') as fp: #出html報(bào)告 runner=HTMLTestRunner.HTMLTestRunner(stream=fp,title=u'測(cè)試報(bào)告',description=u'用例執(zhí)行情況',verbosity=2) suite=createsuite() runner.run(suite)
5 異常捕捉與錯(cuò)誤截圖
用例不可能每一次運(yùn)行都成功,肯定運(yùn)行時(shí)候有不成功的時(shí)候。如果可以捕捉到錯(cuò)誤,并且把錯(cuò)誤截圖保存,這將是一個(gè)非常棒的功能,也會(huì)給我們錯(cuò)誤定位帶來(lái)方便。
例如編寫(xiě)一個(gè)函數(shù),關(guān)鍵語(yǔ)句為driver.get_screenshot_as_file:
def savescreenshot(self,driver,file_name): if not os.path.exists('./image'): os.makedirs('./image') now=time.strftime("%Y%m%d-%H%M%S",time.localtime(time.time())) #截圖保存 driver.get_screenshot_as_file('./image/'+now+'-'+file_name) time.sleep(1)
示例:testscreenshot.py
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoAlertPresentException import unittest, time, re import os class Baidu1(unittest.TestCase): #test fixture,初始化環(huán)境 def setUp(self): self.driver = webdriver.Chrome() self.driver.implicitly_wait(30) self.base_url = "http://www.baidu.com/" self.verificationErrors = [] self.accept_next_alert = True #測(cè)試用例,必須以test開(kāi)頭 def test_hao(self): driver = self.driver driver.get(self.base_url + "/") driver.find_element(By.LINK_TEXT,"hao123").click() time.sleep(2) try: self.assertEqual(u'hao_上網(wǎng)從這里開(kāi)始', driver.title) except: self.savescreenshot(driver,'hao.png') #判斷element是否存在,可刪除 def is_element_present(self, how, what): try: self.driver.find_element(by=how, value=what) except NoSuchElementException as e: return False return True #判斷alert是否存在,可刪除 def is_alert_present(self): try: self.driver.switch_to_alert() except NoAlertPresentException as e: return False return True #關(guān)閉alert,可刪除 def close_alert_and_get_its_text(self): try: alert = self.driver.switch_to_alert() alert_text = alert.text if self.accept_next_alert: alert.accept() else: alert.dismiss() return alert_text finally: self.accept_next_alert = True #test fixture,清除環(huán)境 def tearDown(self): self.driver.quit() self.assertEqual([], self.verificationErrors) def savescreenshot(self,driver,file_name): if not os.path.exists('./image'): os.makedirs('./image') now=time.strftime("%Y%m%d-%H%M%S",time.localtime(time.time())) #截圖保存 driver.get_screenshot_as_file('./image/'+now+'-'+file_name) time.sleep(1) if __name__ == "__main__": #執(zhí)行用例 unittest.main() ''' 可以增加verbosity參數(shù),例如unittest.main(verbosity=2) 在主函數(shù)中,直接調(diào)用main() ,在main中加入verbosity=2 ,這樣測(cè)試的結(jié)果就會(huì)顯示的更加詳細(xì)。 這里的verbosity 是一個(gè)選項(xiàng), 表示測(cè)試結(jié)果的信息復(fù)雜度,有三個(gè)值: 0 ( 靜默模式): 你只能獲得總的測(cè)試用例數(shù)和總的結(jié)果比如總共100個(gè)失敗,20 成功80 1 ( 默認(rèn)模式): 非常類(lèi)似靜默模式只是在每個(gè)成功的用例前面有個(gè)“ . ” 每個(gè)失敗的用例前面有個(gè)“F” 2 ( 詳細(xì)模式): 測(cè)試結(jié)果會(huì)顯示每個(gè)測(cè)試用例的所有相關(guān)的信息 '''
6 數(shù)據(jù)驅(qū)動(dòng)
之前我們的case都是數(shù)據(jù)和代碼在一起編寫(xiě)。考慮如下場(chǎng)景:
需要多次執(zhí)行一個(gè)案例,比如baidu搜索,分別輸入中文、英文、數(shù)字等進(jìn)行搜索,這時(shí)候需要編寫(xiě)3個(gè)案例嗎?有沒(méi)有版本一次運(yùn)行?
python 的unittest 沒(méi)有自帶數(shù)據(jù)驅(qū)動(dòng)功能。所以如果使用unittest,同時(shí)又想使用數(shù)據(jù)驅(qū)動(dòng),那么就可以使用DDT來(lái)完成。
ddt的安裝:
pip install ddt
python setup.py install
dd.ddt:
裝飾類(lèi),也就是繼承自TestCase的類(lèi)。
ddt.data:
裝飾測(cè)試方法。參數(shù)是一系列的值。
data(value) 一次性傳入一個(gè)參數(shù)data(value1,value2,…) 一次性傳入多個(gè)參數(shù),需要用@unpack映射data(*解析數(shù)據(jù)的方法(txt/csv文件))
ddt.file_data:
裝飾測(cè)試方法。參數(shù)是文件名。文件可以是json 或者 yaml類(lèi)型。
注意,如果文件以”.yml”或者”.yaml”結(jié)尾,ddt會(huì)作為yaml類(lèi)型處理,其他所有文件都會(huì)作為json文件處理。
如果文件中是列表,每個(gè)列表的值會(huì)作為測(cè)試用例參數(shù),同時(shí)作為測(cè)試用例方法名后綴顯示。
如果文件中是字典,字典的key會(huì)作為測(cè)試用例方法的后綴顯示,字典的值會(huì)作為測(cè)試用例參數(shù)。
ddt.unpack:
傳遞的是復(fù)雜的數(shù)據(jù)結(jié)構(gòu)時(shí)使用。比如使用元組或者列表,添加unpack之后,ddt會(huì)自動(dòng)把元組或者列表對(duì)應(yīng)到多個(gè)參數(shù)上。字典也可以這樣處理。
Testddt.py:
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select from selenium.common.exceptions import NoSuchElementException from selenium.common.exceptions import NoAlertPresentException import unittest, time, re import os,sys,csv from ddt import ddt, data, unpack ,file_data def getCsv(file_name): rows=[] path=sys.path[0].replace('\testddt','') print (path) with open(path+'/data/'+file_name,'r+b') as f: readers=csv.reader(f,delimiter=',',quotechar='|') next(readers,None) for row in readers: temprows=[] for i in row: temprows.append(i.decode('gbk')) rows.append(temprows) return rows #引入ddt @ddt class Testddt(unittest.TestCase): def setUp(self): self.driver = webdriver.Chrome() self.driver.implicitly_wait(30) self.base_url = "http://www.baidu.com" self.verificationErrors = [] self.accept_next_alert = True #測(cè)試用例,必須以test開(kāi)頭 #增加ddt數(shù)據(jù) @data('selenium','unittest','Junit') #@data(2,3,4) #單變更時(shí)不使用unpack #@data([3, 2], [4, 3], [5, 3]) # @data(*getCsv('test_baidu_data.csv')) #使用file_data需要在cmd窗口下運(yùn)行,否則找不到文件 #@file_data('test_data_list.json') # @unpack def test_hao(self,value,expected_value): # def test_hao(self,value): driver = self.driver driver.get(self.base_url + "/") driver.find_element(By.ID,"kw").clear() driver.find_element(By.ID,"kw").send_keys(value) driver.find_element(By.ID,"su").click() time.sleep(2) self.assertEqual(expected_value, driver.title) print (expected_value) print (driver.title) #判斷element是否存在,可刪除 def is_element_present(self, how, what): try: self.driver.find_element(by=how, value=what) except NoSuchElementException as e: return False return True #判斷alert是否存在,可刪除 def is_alert_present(self): try: self.driver.switch_to_alert() except NoAlertPresentException as e: return False return True #關(guān)閉alert,可刪除 def close_alert_and_get_its_text(self): try: alert = self.driver.switch_to_alert() alert_text = alert.text if self.accept_next_alert: alert.accept() else: alert.dismiss() return alert_text finally: self.accept_next_alert = True #test fixture,清除環(huán)境 def tearDown(self): self.driver.quit() self.assertEqual([], self.verificationErrors) def savescreenshot(self,driver,file_name): if not os.path.exists('./image'): os.makedirs('./image') now=time.strftime("%Y%m%d-%H%M%S",time.localtime(time.time())) #截圖保存 driver.get_screenshot_as_file('./image/'+now+'-'+file_name) time.sleep(1) if __name__ == "__main__": #執(zhí)行用例 unittest.main()
到此這篇關(guān)于Python自動(dòng)化測(cè)試框架之unittest使用詳解的文章就介紹到這了,更多相關(guān)Python unittest內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何通過(guò)pycharm實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的查詢(xún)等操作(非多步操作)
這篇文章主要介紹了如何通過(guò)pycharm實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的查詢(xún)等操作(非多步操作),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07python 字符串和整數(shù)的轉(zhuǎn)換方法
今天小編就為大家分享一篇python 字符串和整數(shù)的轉(zhuǎn)換方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06在Python的Flask框架中實(shí)現(xiàn)全文搜索功能
這篇文章主要介紹了在Python的Flask框架中實(shí)現(xiàn)全文搜索功能,這個(gè)基本的web功能實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單,需要的朋友可以參考下2015-04-04我對(duì)PyTorch dataloader里的shuffle=True的理解
這篇文章主要介紹了我對(duì)PyTorch dataloader里的shuffle=True的理解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05Python中的random.uniform()函數(shù)教程與實(shí)例解析
今天小編就為大家分享一篇關(guān)于Python中的random.uniform()函數(shù)教程與實(shí)例解析,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03Python 利用base64庫(kù) 解碼本地txt文本字符串
這篇文章主要介紹了Python 利用base64庫(kù) 解碼本地txt文本字符串的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04利用pipenv和pyenv管理多個(gè)相互獨(dú)立的Python虛擬開(kāi)發(fā)環(huán)境
這篇文章主要介紹了利用pipenv和pyenv管理多個(gè)相互獨(dú)立的Python虛擬開(kāi)發(fā)環(huán)境,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Python利用邏輯回歸模型解決MNIST手寫(xiě)數(shù)字識(shí)別問(wèn)題詳解
這篇文章主要介紹了Python利用邏輯回歸模型解決MNIST手寫(xiě)數(shù)字識(shí)別問(wèn)題,結(jié)合實(shí)例形式詳細(xì)分析了Python MNIST手寫(xiě)識(shí)別問(wèn)題原理及邏輯回歸模型解決MNIST手寫(xiě)識(shí)別問(wèn)題相關(guān)操作技巧,需要的朋友可以參考下2020-01-01