簡介
大多數的初學者在使用 unittest 框架時候,不清楚用例的執行順序到底是怎樣的。對測試類里面的類和方法分不清楚,不知道什么時候執行,什么時候不執行。雖然或許通過代碼實現了,也是稀里糊塗的一知半解,這樣還好,好歹自己鼓
搗出了,但是時間和效率並不是很高,下次遇到還是老樣子。那么本篇通過最簡單案例來給給為小伙伴詳細講解、演示一下 unittest 執行順序。
實例代碼
參考代碼
1 # coding=utf-8 2 #1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 3 4 #2.注釋:包括記錄創建時間,創建人,項目名稱。 5 ''' 6 Created on 2019-4-23 7 @author: 北京-宏哥 8 Project:學習和使用unittest框架編寫測試用例執行順序 9 ''' 10 #3.導入unittest模塊 11 import unittest 12 #4.執行順序和運行測試 13 import unittest 14 15 class TestLogin(unittest.TestCase): 16 17 def test_login_blog(self): 18 """登錄博客園 19 20 :return: 21 """ 22 23 def test_add_essay(self): 24 """ 添加隨筆 25 26 :return: 27 """ 28 29 def test_release_essay(self): 30 """ 發布隨筆 31 32 :return: 33 """ 34 35 def test_quit_blog(self): 36 """退出博客園 37 38 :return: 39 """ 40 if __name__ == "__main__()": 41 unittest.main()
這是一個標准的使用unittest進行測試的例子,寫完后心里美滋滋,嗯,就按照一貫思路代碼會按照這個順序測就可以了。結果一運行。就傻眼了
這時候自己心里犯嘀咕,這是什么鬼,怎么回事呢。執行的順序亂了。第一個執行的測試用例並不是登錄博客園,而是添加隨筆,此時用戶還沒登錄博客園,進行添加隨筆的話會直接報錯,導致用例失敗。
到這里有些小伙伴可能會說,為什么要讓測試用例之間有所依賴呢?
的確,如果完全沒依賴,測試用例的執行順序是不需要關注的。但是這樣對於用例的設計和實現,要求就高了許多。而對博客園來說,一個系統內的操作,是有很大的關聯性的。以添加隨筆為例,隨筆內的每個操作都有一個前提,你需要
登錄博客園才能添加隨筆。所以要實現用例之間的完全解耦,需要每個用例開始之前,檢測用戶的登錄狀態。
如果可以控制測試用例的執行順序,按照功能流程一遍走下來,節省的代碼量是非常可觀的,閱讀測試用例也會清晰明了許多。
如何控制unittest用例執行的順序呢?
1、帶大家先看看源碼,unittest是怎么樣對用例進行排序的。在loader.py
的loadTestsFromTestCase
方法里邊,調用了getTestCaseNames
方法來獲取測試用例的名稱
2、從源碼可以清楚地看到,getTestCaseNames
方法對測試用例的名稱進行了排序
3、一步一步跟進去,查看其排序方法
4、根據排序規則,unittest執行測試用例,默認是根據ASCII碼的順序加載測試用例,數字與字母的順序為:0-9,A-Z,a-z。
5、做個小demo,看看是不是我們所說的那種排序規則
6、從上邊的運行結果,我們可以看出是:unittest執行測試用例,默認是根據ASCII碼的順序加載測試用例,數字與字母的順序為:0-9,A-Z,a-z。
7、基於unittest的機制,如何控制用例執行順序呢?查了一些網上的資料,主要介紹了兩種方式:
方式1,通過TestSuite類的addTest方法,按順序加載測試用例
參考代碼
1 # coding=utf-8 2 #1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 3 4 #2.注釋:包括記錄創建時間,創建人,項目名稱。 5 ''' 6 Created on 2019-4-23 7 @author: 北京-宏哥 8 Project:學習和使用unittest框架編寫測試用例執行順序 9 ''' 10 #3.導入unittest模塊 11 import unittest 12 #4.執行順序和運行測試 13 import unittest 14 15 class TestLogin(unittest.TestCase): 16 17 def setUp(self): 18 pass 19 def test_login_blog(self): 20 """登錄博客園 21 22 :return: 23 """ 24 print("登錄博客園") 25 def test_add_essay(self): 26 """ 添加隨筆 27 28 :return: 29 """ 30 print("添加隨筆") 31 def test_release_essay(self): 32 """ 發布隨筆 33 34 :return: 35 """ 36 print("發布隨筆") 37 def test_quit_blog(self): 38 """退出博客園 39 40 :return: 41 """ 42 print("退出博客園") 43 44 def tearDown(self): 45 pass 46 if __name__ == '__main__': 47 # 啟動單元測試 48 # unittest.main() 49 50 # 獲取TestSuite的實例對象 51 suite = unittest.TestSuite() 52 53 # 將測試用例添加到測試容器中 54 suite.addTest(TestLogin('test_login_blog')) 55 suite.addTest(TestLogin('test_add_essay')) 56 suite.addTest(TestLogin('test_release_essay')) 57 suite.addTest(TestLogin('test_quit_blog')) 58 59 # 創建TextTestRunner類的實例對象 60 runner = unittest.TextTestRunner() 61 runner.run(suite) 62 #unittest.TextTestRunner(verbosity=3).run(suite)
方式2,通過修改函數名的方式
參考代碼
1 # coding=utf-8 2 #1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 3 4 #2.注釋:包括記錄創建時間,創建人,項目名稱。 5 ''' 6 Created on 2019-4-23 7 @author: 北京-宏哥 8 Project:學習和使用unittest框架編寫測試用例執行順序 9 ''' 10 #3.導入unittest模塊 11 import unittest 12 #4.執行順序和運行測試 13 import unittest 14 15 class TestLogin(unittest.TestCase): 16 17 def setUp(self): 18 pass 19 def test_1_login_blog(self): 20 """登錄博客園 21 22 :return: 23 """ 24 print("登錄博客園") 25 def test_2_add_essay(self): 26 """ 添加隨筆 27 28 :return: 29 """ 30 print("添加隨筆") 31 def test_3_release_essay(self): 32 """ 發布隨筆 33 34 :return: 35 """ 36 print("發布隨筆") 37 def test_4_quit_blog(self): 38 """退出博客園 39 40 :return: 41 """ 42 print("退出博客園") 43 44 def tearDown(self): 45 pass 46 if __name__ == '__main__': 47 # 啟動單元測試 48 unittest.main()
拓展練習
1、實例
2、運行結果
3、運行結果分析
1、從運行結果可以看出執行順序:
start!-執行測試用例 01-end!
start!-執行測試用例 02-end!
start!-執行測試用例 03-end!
2、從執行結果可以看出幾點
--先執行的前置 setUp,然后執行的用例(test*),最后執行的后置 tearDown
--測試用例(test*)的執行順序是根據 01-02-03 執行的,也就是說根據用例名稱來順序執行的
--addtest(self)這個方法沒執行,說明只執行 test 開頭的用例
參考代碼
1 # coding=utf-8 2 #1.先設置編碼,utf-8可支持中英文,如上,一般放在第一行 3 4 #2.注釋:包括記錄創建時間,創建人,項目名稱。 5 ''' 6 Created on 2019-4-23 7 @author: 北京-宏哥 8 Project:學習和使用unittest框架編寫測試用例思路 9 ''' 10 #3.導入unittest模塊 11 import unittest 12 13 #4.執行順序和運行測試 14 import time 15 class Test(unittest.TestCase): 16 def setUp(self): 17 print ("start!") 18 def tearDown(self): 19 time.sleep(1) 20 print ("end!") 21 def test01(self): 22 print ("執行測試用例 01") 23 def test03(self): 24 print ("執行測試用例 03") 25 def test02(self): 26 print ("執行測試用例 02") 27 def addtest(self): 28 print ("add 方法") 29 if __name__ == "__main__": 30 unittest.main()
小結
1、這個執行順序,看似簡單,實則不簡單,只有掌握最簡單的才可以應付最復雜的。
2、setUp()
和tearDown()
方法有什么用呢?設想你的測試需要啟動一個數據庫,這時,就可以在setUp()
方法中連接數據庫,在tearDown()
方法中關閉數據庫,這樣,不必在每個測試方法中重復相同的代碼。