1、Unittest單元測試框架簡介python
Unitest是Python下的一個單元測試模塊,是Python標準庫模塊之一,安裝完Python後就能夠直接import該模塊,能在單元測試下編寫具體的測試用例腳本,並調用模塊封裝好的方法,實現測試用例的執行、測試場景的恢復,甚至能批量採集測試用例腳本、批量運行測試腳本用例、控制執行順序等,依託於Unittest模塊,能夠高效的組織測試用例編寫、測試用例腳本的採集管理以及腳本運行的執行控制等。Unitest單元測試框架主要包含以下幾個重要的邏輯單元:web
1.測試固件(test fixture)
一個測試固件包括兩部分,執行測試代碼的前置條件和測試結束以後的場景恢復,這兩部分通常用函數setUp()和tearDown()表示。簡單說,就是平時手工測試一條具體的測試用例時,測試的前置環境和測試結束後的環境恢復。
2.測試用例(test case)
unittest中管理的最小單元是測試用例,就是一個測試用例,包括具體測試業務的函數或者方法,只是該test case 必須是以test開頭的函數。unittest會自動化識別test開頭的函數是測試代碼,若是你寫的函數不是test開頭,unittest是不會執行這個函數裏面的腳本,這個千萬要記住,全部的測試函數都要test開頭,記住是小寫的哦。
3.測試套件 (test suite)
就是不少測試用例的集合,一個測試套件能夠隨意管理多個測試用例,該部分用來實現諸多測試用例的採集,造成一套測試用例集。
4.測試執行器 (test runner)
test runner是一個用來執行加載測試用例,並執行用例,且提供測試輸出的一個邏輯單元。test runner能夠加載test case或者test suite進行執行測試任務,並能控制用例集的執行順序等。瀏覽器
從Unitest單元測試框架的基本邏輯單元設計來看,很明顯能夠看到它包含了用例的整個生命週期:用例的前置條件、用例的編寫、用例的採集、用例的執行以及測試執行後的場景恢復。框架
二、首次使用Unittest模塊函數
下面以打開百度,進行搜索,建立一個名爲baidu_search.py的腳本文件,編寫百度搜索分別python2和python3的測試用例,代碼以下:單元測試
''' Code description: Create time: Developer: ''' # -*- coding: utf-8 -*- import time import unittest from selenium import webdriver class Search(unittest.TestCase): def setUp(self): """ 測試前置條件,這裏要搜索的話就是先得打開百度網站啦 """ self.driver = webdriver.Ie() self.driver.maximize_window() self.driver.implicitly_wait(5) self.driver.get("https://www.baidu.com") def tearDown(): """ 測試結束後環境復原,這裏就是瀏覽器關閉退出 """ self.driver.quit() def test_search1(self): """ 這裏必定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。 """ self.driver.find_element_by_id('kw').send_keys('python2') self.driver.find_element_by_id('su').click() time.sleep(1) try: assert 'python2' in self.driver.title print('檢索python2完成') except Exception as e: print('檢索失敗', format(e)) def test_search2(self): """ 這裏必定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。 """ self.driver.find_element_by_id('kw').send_keys('python3') self.driver.find_element_by_id('su').click() time.sleep(1) try: assert 'python3' in self.driver.title print('檢索python3完成') except Exception as e: print('檢索失敗', format(e)) if __name__ == '__main__': unittest.main()
在PyCharm中運行上面代碼,咱們會發現瀏覽器打開關閉了兩次,分別檢索了python2關閉瀏覽器,而後檢索python3關閉瀏覽器。測試
這個效果顯然不是咱們但願的,咱們但願檢索完python2後,不用關閉瀏覽器繼續檢索python3,Unittest有相關的設置嗎?答案是確定的,咱們對以上代碼作下調整修改,注意對比不一樣的地方,而後運行就達到咱們想要的效果網站
''' Code description: Create time: Developer: ''' # -*- coding: utf-8 -*- import time import unittest from selenium import webdriver class Search(unittest.TestCase): @classmethod def setUpClass(cls): """ 測試前置條件,這裏要搜索的話就是先得打開百度網站啦 """ cls.driver = webdriver.Ie() cls.driver.maximize_window() cls.driver.implicitly_wait(5) cls.driver.get("https://www.baidu.com") @classmethod def tearDownClass(cls): """ 測試結束後環境復原,這裏就是瀏覽器關閉退出 """ cls.driver.quit() def test_search1(self): """ 這裏必定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。 """ self.driver.find_element_by_id('kw').send_keys('python2') self.driver.find_element_by_id('su').click() time.sleep(1) try: assert 'python2' in self.driver.title print('檢索python2完成') except Exception as e: print('檢索失敗', format(e)) def test_search2(self): """ 這裏必定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。 """ self.driver.find_element_by_id('kw').clear() # 清空以前輸入的python2 self.driver.find_element_by_id('kw').send_keys('python3') self.driver.find_element_by_id('su').click() time.sleep(1) try: assert 'python3' in self.driver.title print('檢索python3完成') except Exception as e: print('檢索失敗', format(e)) if __name__ == '__main__': unittest.main()
三、Unittest模塊批量加載和管理用例ui
以上對於Unittest框架,咱們好像只用到了測試固件、測試用例兩個邏輯單元的使用,接下來問題又來了:咱們平常項目中的測試案例確定不止一個,當案例愈來愈多時咱們如何管理這些批量案例?如何保證案例不重複?若是案例很是多(成百上千,甚至更多)時如何保證案例執行的效率?設計
來看一下在unittest框架中如何管理批量用例:
手動添加採集指定的測試用例集用法:先在PyCharm中新建以下項目層級:
其中baidu_search1仍是上面調整修改過的代碼,而後編輯run_case.py文件,代碼以下:
''' Code description: 執行add 的測試用例集 Create time: Developer: ''' # -*- coding: utf-8 -*- from testcase.sreach.baidu_sreach1 import Search # 將baidu_sreach.py模塊導入進來 import unittest suite = unittest.TestSuite() # 構造測試用例集 # suite.addTest(Search("test_search1")) suite.addTest(Search("test_search2")) # 分別添加baidu_sreach1.py中的兩個檢索的測試用例 if __name__ == '__main__': runner = unittest.TextTestRunner() # 實例化runner runner.run(suite) #執行測試
這樣運行run_case.py,就只執行了在百度中搜索python3這條用例,手動添加指定用例到測試套件的方法是addTest(),可是不少時候咱們寫了不少測試腳本文件,每一個腳本中有多個test,,若是仍是使用addTest()方法就不行了,咱們但願能獲取全部的測試集,並所有執行。而後編輯run_all_case.py文件,編寫以下代碼:
''' Code description: TestLoader全部測試case Create time: Developer: ''' # -*- coding: utf-8 -*- import time import os.path import unittest from selenium import webdriver class Search(unittest.TestCase): @classmethod def setUpClass(cls): """ 測試前置條件,這裏要搜索的話就是先得打開百度網站啦 """ cls.driver = webdriver.Ie() cls.driver.maximize_window() cls.driver.implicitly_wait(5) cls.driver.get("https://www.baidu.com") @classmethod def tearDownClass(cls): """ 測試結束後環境復原,這裏就是瀏覽器關閉退出 """ cls.driver.quit() def test_search1(self): """ 這裏必定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。 """ self.driver.find_element_by_id('kw').send_keys('python2') self.driver.find_element_by_id('su').click() time.sleep(1) try: assert 'python2' in self.driver.title print('檢索python2完成') except Exception as e: print('檢索失敗', format(e)) def test_search2(self): """ 這裏必定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。 """ self.driver.find_element_by_id('kw').clear() # 清空以前輸入的python2 self.driver.find_element_by_id('kw').send_keys('python3') self.driver.find_element_by_id('su').click() time.sleep(1) try: assert 'python3' in self.driver.title print('檢索python3完成') except Exception as e: print('檢索失敗', format(e)) def test_search3(self): """ 這裏必定要test開頭,把測試邏輯代碼封裝到一個test開頭的方法裏。 """ self.driver.find_element_by_id('kw').clear() # 清空以前輸入的python3 self.driver.find_element_by_id('kw').send_keys('hello world') self.driver.find_element_by_id('su').click() time.sleep(1) try: assert 'hello world' in self.driver.title print('檢索hello world完成') except Exception as e: print('檢索失敗', format(e)) case_path = os.path.join(os.getcwd()) # 在當前目錄中採集測試用例 print(case_path) all_case = unittest.defaultTestLoader.discover(case_path, pattern="test*.py", top_level_dir=None) # 採集全部test開頭的測試用例 print(all_case) if __name__ == '__main__': runner = unittest.TextTestRunner() # 實例化runner runner.run(all_case) # 執行測試
獲取全部的測試用例集使用的是discover()方法,在PyCharm中運行該腳本就以下:
以上就完成了在Python Unittest單元測試框架下編寫測試用例腳本,並使用其提供的多種方法來批量管理測試用例集並並執行。