
Unittest
unittest大家應該都不陌生,它作為一款博主在5-6年前最常用的單元測驗框架,現在正被pytest,nose慢慢蠶食,
漸漸地,看到大家更多的討論的內容從unittest+HTMLTestRunner變為pytest+allure2等后起之秀,
不禁感慨,終究是自己落伍了,跟不上時代的大潮了,
回到主題
感慨完了,回到正文,雖然unittest正在慢慢被放棄,但是它仍然是一款很全面的測驗框架,
今天在群里看到有個群友的一番言論,激起了我的一番回憶,
自己以前是知道unittest的執行順序并不是按照撰寫test方法的順序執行,而是按照字典序執行的,但遺憾的是我都是投機取巧去解決的問題(后面會講),
下面我們就來探討下unittest類的test方法的執行順序問題,
原始碼初窺
研究一下原始碼(unittest.TestLoader)可以發現,在加載一個class下面的test方法的時候,原生Loader進行了排序,并且根據functools.cmp_to_key方法對測驗方法串列進行了排序,

我們知道,unittest是不需要我們指定對應的方法,說白了,它是從類里面自動獲取到咱們的方法,并約定了以test開頭的方法都會被視為測驗方法,

查詢一下self.sortTestMethodsUsing(這個是一個排序的方式),

可以看到這個比較方法寫的很明確了,如果x < y那么回傳-1,x = y則回傳0,x > y回傳1,
其實大家可能不知道Python里面的字串也是可以比較的,在此必須說明一下字典序,我們來看看這個例子:
a = "abc"
b = "abcd"
c = "abce"
print(a > b)
print(b > c)
猜猜看執行結果,很顯然,字典序的比較,是按A-Z的順序來比較的,如果前綴一樣但長度不一樣,那么長度長的那個,字典序靠后,

了解了字典序以后,我們就不難知道,在unittest里面它尋找case的程序可以這樣簡化:
-
找到對應類下面以test開頭的測驗方法
-
對他們進行字典序排序
-
依次執行
這樣就不難解釋為什么我們有時候寫的case不按照自己想的順序來,
回到問題的本質
搞清楚為什么用例會亂,那就想到對應的解決方案,由于修改原始碼是不太合適的,那我們有2個策略去達成目的,
比如我有多個test方法:
class Testcase(unittest.TestCase):
def setUp(self) -> None:
pass
def test_1(self):
print("執行第一個")
def test_2(self):
print("第二個")
def test_3(self):
print("第三個")
def test_10(self):
print("第四個")
def test_11(self):
print("第五個")
def tearDown(self) -> None:
pass
if __name__ == "__main__":
unittest.main()
執行起來,按照字典序,其實是1 10 11 2 3的順序,

1. 以字典序的方式撰寫test方法
我們可以手動修改test方法的名稱,這也是我早前的處理方式,也就是說把想要先執行的case字典序排到前面:
class Testcase(unittest.TestCase):
def setUp(self) -> None:
pass
def test_0_1(self):
print("執行第一個")
def test_0_2(self):
print("第二個")
def test_0_3(self):
print("第三個")
def test_1_0(self):
print("第四個")
def test_1_1(self):
print("第五個")
def tearDown(self) -> None:
pass
我們可以把數字按位數拆開,個位數就把10位補0,這樣就能達到效果,如果會寫100個case,我們就需要補2個0,比如0_0_1,當然一個檔案里面也不會有太多case,
如果遇到test_login這種怎么辦呢,不是數字結尾的方法,
其實是一樣的,可以寫成test_數字_業務的模式,番貨寫了一個裝飾器專門解決這樣的問題,大家可以去參考下,
2. 回歸本質,從根本解決問題
方案1用了番貨的裝飾器,好是好,但是改變了方法本身的名稱,我們其實可以針對他的排序方式入手,按照我們撰寫case的順序排序測驗方法,就能達到想要的目的,
說說思路:
- 手寫一個loader繼承自TestLoader類,改寫里面的排序方法
- 在unittest運行的時候傳入這個新的loader
來看看完整代碼,注釋里面寫的很完善了,
import unittest
class MyTestLoader(unittest.TestLoader):
def getTestCaseNames(self, testcase_class):
# 呼叫父類的獲取“測驗方法”函式
test_names = super().getTestCaseNames(testcase_class)
# 拿到測驗方法list
testcase_methods = list(testcase_class.__dict__.keys())
# 根據list的索引對testcase_methods進行排序
test_names.sort(key=testcase_methods.index)
# 回傳測驗方法名稱
return test_names
class Testcase(unittest.TestCase):
def setUp(self) -> None:
pass
def test_1(self):
print("執行第一個")
def test_2(self):
print("第二個")
def test_3(self):
print("第三個")
def test_10(self):
print("第四個")
def test_11(self):
print("第五個")
def tearDown(self) -> None:
pass
if __name__ == "__main__":
unittest.main(testLoader=MyTestLoader())

執行了一下還是不對,是不是哪里出了什么問題呢?
是因為pycharm有一種默認的unittest的除錯方法,我們要改成普通的方法去執行,




試試用控制臺執行:

今天的內容就講到這里了,看懂的記得給個贊哦~

最后: 可以關注公眾號:傷心的辣條 ! 進去有許多資料共享!資料都是面試時面試官必問的知識點,也包括了很多測驗行業常見知識,其中包括了有基礎知識、Linux必備、Shell、互聯網程式原理、Mysql資料庫、抓包工具專題、介面測驗工具、測驗進階-Python編程、Web自動化測驗、APP自動化測驗、介面自動化測驗、測驗高級持續集成、測驗架構開發測驗框架、性能測驗、安全測驗等,
如果我的博客對你有幫助、如果你喜歡我的博客內容,請 “點贊” “評論” “收藏” 一鍵三連哦!推薦軟體測驗交流學習群:914172719 里面會分享一些資深架構師錄制的視頻錄像
好文推薦
轉行面試,跳槽面試,軟體測驗人員都必須知道的這幾種面試技巧!
面試經:一線城市搬磚!又面軟體測驗崗,5000就知足了…
面試官:作業三年,還來面初級測驗?恐怕你的軟體測驗工程師的頭銜要加雙引號…
什么樣的人適合從事軟體測驗作業?
那個準點下班的人,比我先升職了…
測驗崗反復跳槽,跳著跳著就跳沒了…
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/300688.html
標籤:其他
上一篇:網路安全--SQL注入介紹
