unittest-單元測試框架
unittest是受JUnit啟發編寫的一款Python語言的單元測試框架,並與其他語言中的主流單元測試框架有着相似的風格。unittest支持自動化測,測試准備和測試清理部分代碼復用,支持將測試用例組聚合成測試套件,並與報告生成框架相互獨立。
為了實現這些,unittest通過面向對象的方式支持了以下一些重要的概念。
test fixture測試腳手架
test fixture表示為了開展一項或多項測試所需要進行的准備工作,以及所有相關的清理操作。舉個例子,這可能包含創建臨時或代理的數據庫、目錄,再或者啟動一個服務器進程等等。
test case測試用例
一個測試用例是一個獨立的測試單元。它檢查輸入特定的數據時的響應。 unittest 提供一個基類: TestCase ,用於新建測試用例。
test suite測試套件
test suite 是一系列的測試用例,或測試套件,或兩者皆有。它用於歸檔需要一起執行的測試。
test runner 測試運行器
test runner 是一個用於執行和輸出測試結果的組件。這個運行器可能使用圖形接口、文本接口,或返回一個特定的值表示運行測試的結果。
基本示例
unittest 模塊提供了一系列創建和運行測試的工具。這一段演示了這些工具的一小部分,但也足以滿足大部分用戶的需求。
這是一段簡短的代碼,來測試三種字符串方法:
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
def test_isupper(self):
self.assertTrue('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
# check that s.split fails when the separator is not a string
with self.assertRaises(TypeError):
s.split(2)
if __name__ == '__main__':
unittest.main()
繼承 unittest.TestCase 就創建了一個測試用例。上述三個獨立的測試是三個類的方法,這些方法的命名都以 test 開頭。 這個命名約定告訴測試運行者類的哪些方法表示測試用例。
每個測試的關鍵是:調用 assertEqual() 來檢查預期的輸出; 調用 assertTrue() 或 assertFalse() 來驗證一個條件;調用 assertRaises() 來驗證拋出了一個特定的異常。使用這些方法而不是 assert 語句是為了讓測試運行者能聚合所有的測試結果並產生結果報告。
通過 setUp() 和 tearDown() 方法,可以設置測試開始前與完成后需要執行的指令。 在 組織你的測試代碼 中,對此有更為詳細的描述。
最后的代碼塊中,演示了運行測試的一個簡單的方法。 unittest.main() 提供了一個測試腳本的命令行接口。當在命令行運行該測試腳本,上文的腳本生成如以下格式的輸出:
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
在調用測試腳本時添加 -v 參數使 unittest.main() 顯示更為詳細的信息,生成如以下形式的輸出:
test_isupper (__main__.TestStringMethods) ... ok
test_split (__main__.TestStringMethods) ... ok
test_upper (__main__.TestStringMethods) ... ok
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
以上例子演示了 unittest 中最常用的、足夠滿足許多日常測試需求的特性。文檔的剩余部分詳述該框架的完整特性。
命令行界面
unittest 模塊可以通過命令行運行模塊、類和獨立測試方法的測試:
python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
你可以傳入模塊名、類或方法名或他們的任意組合。
同樣的,測試模塊可以通過文件路徑指定:
python -m unittest tests/test_something.py
這樣就可以使用 shell 的文件名補全指定測試模塊。所指定的文件仍需要可以被作為模塊導入。路徑通過去除 '.py' 、把分隔符轉換為 '.' 轉換為模塊名。若你需要執行不能被作為模塊導入的測試文件,你需要直接執行該測試文件。
在運行測試時,你可以通過添加 -v 參數獲取更詳細(更多的冗余)的信息。
python -m unittest -v test_module
當運行時不包含參數,開始 探索性測試
python -m unittest
用於獲取命令行選項列表:
python -m unittest -h
在 3.2 版更改: 在早期版本中,只支持運行獨立的測試方法,而不支持模塊和類。
命令行選項
unittest支持以下命令行選項:
-b, --buffer
在測試運行時,標准輸出流與標准錯誤流會被放入緩沖區。成功的測試的運行時輸出會被丟棄;測試不通過時,測試運行中的輸出會正常顯示,錯誤會被加入到測試失敗信息。
-c, --catch
當測試正在運行時, Control-C 會等待當前測試完成,並在完成后報告已執行的測試的結果。當再次按下 Control-C 時,引發平常的 KeyboardInterrupt 異常。
See Signal Handling for the functions that provide this functionality.
-f, --failfast
當出現第一個錯誤或者失敗時,停止運行測試。
-k
只運行匹配模式或子串的測試方法和類。可以多次使用這個選項,以便包含匹配子串的所有測試用例。
包含通配符(*)的模式使用 fnmatch.fnmatchcase() 對測試名稱進行匹配。另外,該匹配是大小寫敏感的。
模式對測試加載器導入的測試方法全名進行匹配。
例如,-k foo 可以匹配到 foo_tests.SomeTest.test_something 和 bar_tests.SomeTest.test_foo ,但是不能匹配到 bar_tests.FooTest.test_something 。
--locals
在回溯中顯示局部變量。
3.2 新版功能: 添加命令行選項 -b, -c 和 -f 。
3.5 新版功能: 命令行選項 --locals 。
3.7 新版功能: 命令行選項 -k 。
命令行亦可用於探索性測試,以運行一個項目的所有測試或其子集。
探索性測試
3.2 新版功能.
unittest支持簡單的測試搜索。若需要使用探索性測試,所有的測試文件必須是 modules 或 packages (包括 namespace packages )並可從項目根目錄導入(即它們的文件名必須是有效的 identifiers )。
探索性測試在 TestLoader.discover() 中實現,但也可以通過命令行使用。它在命令行中的基本用法如下:
cd project_directory
python -m unittest discover
注意: 方便起見,
python -m unittest
與python -m unittest discover
等價。如果你需要向探索性測試傳入參數,必須顯式地使用 discover 子命令。
discover 有以下選項:
-v, --verbose
更詳細地輸出結果。
-s, --start-directory directory
開始進行搜索的目錄(默認值為當前目錄 . )。
-p, --pattern pattern
用於匹配測試文件的模式(默認為 test*.py )。
-t, --top-level-directory directory
指定項目的最上層目錄(通常為開始時所在目錄)。
-s ,-p 和 -t 選項可以按順序作為位置參數傳入。以下兩條命令是等價的:
python -m unittest discover -s project_directory -p "*_test.py"
python -m unittest discover project_directory "*_test.py"
正如可以傳入路徑那樣,傳入一個包名作為起始目錄也是可行的,如 myproject.subpackage.test 。你提供的包名會被導入,它在文件系統中的位置會被作為起始目錄。
警告 探索性測試通過導入測試對測試進行加載。在找到所有你指定的開始目錄下的所有測試文件后,它把路徑轉換為包名並進行導入。如 foo/bar/baz.py 會被導入為 foo.bar.baz 。
如果你有一個全局安裝的包,並嘗試對這個包的副本進行探索性測試,可能會從錯誤的地方開始導入。如果出現這種情況,測試會輸出警告並退出。
如果你使用包名而不是路徑作為開始目錄,搜索時會假定它導入的是你想要的目錄,所以你不會收到警告。
測試模塊和包可以通過 load_tests protocol 自定義測試的加載和搜索。
在 3.4 版更改: 探索性測試支持命名空間包( namespace packages )。
用例組織
單元測試的構建單位是 test cases :獨立的、包含執行條件與正確性檢查的方案。在 unittest 中,測試用例表示為 unittest.TestCase 的實例。通過編寫 TestCase 的子類或使用 FunctionTestCase 編寫你自己的測試用例。
一個 TestCase 實例的測試代碼必須是完全自含的,因此它可以獨立運行,或與其它任意組合任意數量的測試用例一起運行。
TestCase 的最簡單的子類需要實現一個測試方法(例如一個命名以 test 開頭的方法)以執行特定的測試代碼:
import unittest
class DefaultWidgetSizeTestCase(unittest.TestCase):
def test_default_widget_size(self):
widget = Widget('The widget')
self.assertEqual(widget.size(), (50, 50))
可以看到,為了進行測試,我們使用了基類 TestCase 提供的其中一個 assert*() 方法。若測試不通過,將會引發一個帶有說明信息的異常,並且 unittest 會將這個測試用例標記為測試不通過。任何其它類型的異常將會被當做錯誤處理。
可能同時存在多個前置操作相同的測試,我們可以把測試的前置操作從測試代碼中拆解出來,並實現測試前置方法 setUp() 。在運行測試時,測試框架會自動地為每個單獨測試調用前置方法。
import unittest
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget('The widget')
def test_default_widget_size(self):
self.assertEqual(self.widget.size(), (50,50),
'incorrect default size')
def test_widget_resize(self):
self.widget.resize(100,150)
self.assertEqual(self.widget.size(), (100,150),
'wrong size after resize')
注意:多個測試運行的順序由內置字符串排序方法對測試名進行排序的結果決定。
在測試運行時,若 setUp() 方法引發異常,測試框架會認為測試發生了錯誤,因此測試方法不會被運行。
相似的,我們提供了一個 tearDown() 方法在測試方法運行后進行清理工作。
import unittest
class WidgetTestCase(unittest.TestCase):
def setUp(self):
self.widget = Widget('The widget')
def tearDown(self):
self.widget.dispose()
若 setUp() 成功運行,無論測試方法是否成功,都會運行 tearDown() 。
這樣的一個測試代碼運行的環境被稱為 test fixture 。一個新的 TestCase 實例作為一個測試腳手架,用於運行各個獨立的測試方法。在運行每個測試時,setUp() 、tearDown() 和 init() 會被調用一次。
建議使用 TestCase 實現根據測試測試的功能將測試分組在一起。單元測試為此提供了一種機制:測試套件,由單元測試的TestSuite類表示。在大多數情況下,調用unittest.main()將做正確的事並收集模塊的所有測試用例並執行它們。
然而,如果你需要自定義你的測試套件的話,你可以參考以下方法組織你的測試:
def suite():
suite = unittest.TestSuite()
suite.addTest(WidgetTestCase('test_default_widget_size'))
suite.addTest(WidgetTestCase('test_widget_resize'))
return suite
if __name__ == '__main__':
runner = unittest.TextTestRunner()
runner.run(suite())
你可以將測試用例和測試套件的定義放在被測代碼碼相同的模塊(如widget.py)中, ,但將測試代碼放在單獨的模塊(如test_widget.py)中有以下幾個優點 :
- 測試模塊可以從命令行獨立運行。
- 測試代碼可以更容易地與已發貨代碼分離。
- 在沒有充分理由的情況下更改測試代碼以適應其測試的代碼的誘惑較小。
- 測試代碼的修改頻率應比測試的代碼少得多。
- 測試的代碼可以更容易地重構。
- 不管怎樣,用 C 編寫的模塊的測試必須在單獨的模塊中,那么為什么不保持一致呢?
- 如果測試策略發生更改,則無需更改源代碼。
復用已有的測試代碼
一些用戶希望直接使用 unittest 運行已有的測試代碼,而不需要把已有的每個測試函數轉化為一個 TestCase 的子類。
因此, unittest 提供 FunctionTestCase 類。這個 TestCase 的子類可用於打包已有的測試函數,並支持設置前置與后置函數。
假定有一個測試函數:
def testSomething():
something = makeSomething()
assert something.name is not None
# ...
可以創建等價的測試用例如下,其中前置和后置方法是可選的。
testcase = unittest.FunctionTestCase(testSomething,
setUp=makeSomethingDB,
tearDown=deleteSomethingDB)
注意:盡管函數測試案例可用於將現有測試庫快速轉換為基於單元測試的系統,但不建議使用此方法。花時間設置正確的TestCase子類將使未來的測試重構變得無限容易。
跳過及預期失敗
3.1 新版功能.
unittest 支持跳過單個測試方法,甚至整個測試類。此外,它支持將測試標記為"預期失敗",該測試已損壞且將失敗,但不應算作測試結果的失敗。
跳過測試只是使用skip() 修飾器或其條件變體之一、在 setUp() 或測試方法中調用TestCase.skipTest()或直接引發SkipTest的問題。
跳過測試的基本用法如下:
class MyTestCase(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def test_nothing(self):
self.fail("shouldn't happen")
@unittest.skipIf(mylib.__version__ < (1, 3),
"not supported in this library version")
def test_format(self):
# Tests that work for only a certain version of the library.
pass
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_windows_support(self):
# windows specific testing code
pass
def test_maybe_skipped(self):
if not external_resource_available():
self.skipTest("external resource not available")
# test code that depends on the external resource
pass
在詳細模式下運行以上測試例子時,程序輸出如下:
test_format (__main__.MyTestCase) ... skipped 'not supported in this library version'
test_nothing (__main__.MyTestCase) ... skipped 'demonstrating skipping'
test_maybe_skipped (__main__.MyTestCase) ... skipped 'external resource not available'
test_windows_support (__main__.MyTestCase) ... skipped 'requires Windows'
----------------------------------------------------------------------
Ran 4 tests in 0.005s
OK (skipped=4)
跳過測試類的寫法跟跳過測試方法的寫法相似:
@unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase):
def test_not_run(self):
pass
TestCase.setUp() 也可以跳過測試。可以用於所需資源不可用的情況下跳過接下來的測試。
使用 expectedFailure() 裝飾器表明這個測試預計失敗。:
class ExpectedFailureTestCase(unittest.TestCase):
@unittest.expectedFailure
def test_fail(self):
self.assertEqual(1, 0, "broken")
當要跳過測試時,通過創建在測試中調用skip() 的修飾器,可以輕松滾動自己的跳過修飾器。此修飾器將跳過測試,除非傳遞的對象具有特定屬性:
def skipUnlessHasattr(obj, attr):
if hasattr(obj, attr):
return lambda func: func
return unittest.skip("{!r} doesn't have {!r}".format(obj, attr))
The following decorators and exception implement test skipping and expected failures:
@unittest.skip(reason)
跳過被此裝飾器裝飾的測試。 reason 為測試被跳過的原因。
@unittest.skipIf(condition, reason)
當 condition 為真時,跳過被裝飾的測試。
@unittest.skipUnless(condition, reason)
跳過被裝飾的測試,除非 condition 為真。
@unittest.expectedFailure
把測試標記為預計失敗。如果測試不通過,會被認為測試成功;如果測試通過了,則被認為是測試失敗。
exception unittest.SkipTest(reason)
引發此異常以跳過一個測試。
通常來說,你可以使用 TestCase.skipTest() 或其中一個跳過測試的裝飾器實現跳過測試的功能,而不是直接引發此異常。
被跳過的測試的 setUp() 和 tearDown() 不會被運行。被跳過的類的 setUpClass() 和 tearDownClass() 不會被運行。被跳過的模組的 setUpModule() 和 tearDownModule() 不會被運行。
使用subTest區分測試迭代
3.4 新版功能.
當測試(例如某些參數)之間差異非常小時,單元測試允許您使用subTest() 上下文管理器在測試方法的主體內區分它們。
例如,以下測試:
class NumbersTest(unittest.TestCase):
def test_even(self):
"""
Test that numbers between 0 and 5 are all even.
"""
for i in range(0, 6):
with self.subTest(i=i):
self.assertEqual(i % 2, 0)
可以得到以下輸出:
======================================================================
FAIL: test_even (__main__.NumbersTest) (i=1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "subtests.py", line 32, in test_even
self.assertEqual(i % 2, 0)
AssertionError: 1 != 0
======================================================================
FAIL: test_even (__main__.NumbersTest) (i=3)
----------------------------------------------------------------------
Traceback (most recent call last):
File "subtests.py", line 32, in test_even
self.assertEqual(i % 2, 0)
AssertionError: 1 != 0
======================================================================
FAIL: test_even (__main__.NumbersTest) (i=5)
----------------------------------------------------------------------
Traceback (most recent call last):
File "subtests.py", line 32, in test_even
self.assertEqual(i % 2, 0)
AssertionError: 1 != 0
Without using a subtest, execution would stop after the first failure, and the error would be less easy to diagnose because the value of i wouldn't be displayed:
======================================================================
FAIL: test_even (__main__.NumbersTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "subtests.py", line 32, in test_even
self.assertEqual(i % 2, 0)
AssertionError: 1 != 0
unittest中的類與函數
本節深入介紹了 unittest 的 API。
測試用例
TestCase類
class unittest.TestCase(methodName='runTest')
TestCase 類的實例表示單元測試宇宙中的邏輯測試單元。此類旨在用作基類,具體子類將實現特定測試。此類實現測試運行程序所需的接口,以允許它驅動測試,以及測試代碼可用於檢查和報告各種故障的方法。
TestCase 的每個實例都將運行一個基方法:名為 方法名的方法。在大多數使用TestCase 時,既不會更改方法Name,也不會重新實現默認方法。runTest()
在版本 3.2 中更改:無需提供方法Name 即可成功實例化測試用例。這使得從交互式解釋器試用TestCase更加容易。
TestCase實例提供了三組方法:一組用於運行測試,另一組用於測試實現用於檢查條件和報告失敗,以及允許收集有關測試本身的信息的一些查詢方法。
第一組(運行測試)中的方法為:
setUp()
為准備測試夾具而調用的方法。在調用測試方法之前,立即調用此調用;除了斷言錯誤或跳過測試之外,此方法引發的任何異常都將被視為錯誤而不是測試失敗。默認實現不執行任何操作。
tearDown()
在調用測試方法並記錄結果后立即調用方法。即使測試方法引發異常,也調用此選項,因此子類中的實現可能需要特別小心地檢查內部狀態。此方法引發的任何異常(除斷言錯誤或SkipTest外)將被視為附加錯誤,而不是測試失敗(從而增加報告錯誤的總數)。只有在setUp() 成功時,無論測試方法的結果如何,都將調用此方法。默認實現不執行任何操作。
setUpClass()
運行在單個類中測試之前調用的類方法。 使用 類調用作為唯一的參數,並且必須修飾為一個類方法):setUpClass
@classmethod
def setUpClass(cls):
...
查看 類及模塊級Fixtures 獲取更詳細的說明。
3.2 新版功能.
tearDownClass()
A class method called after tests in an individual class have run. tearDownClass is called with the class as the only argument and must be decorated as a classmethod():
@classmethod
def tearDownClass(cls):
...
查看 類及模塊級Fixtures 獲取更詳細的說明。
3.2 新版功能.
run(result=None)
運行測試,將結果收集到通過結果的測試結果對象中。如果省略結果或 ,則創建一個臨時結果對象(通過調用默認的TestResult()方法)並使用。將結果對象返回到run() 的調用方。None
只需調用 TestCase 實例,即可產生相同的效果。
在版本 3.3 中更改:以前的版本未返回結果。調用實例也沒有調用實例。run
skipTest(reason)
在測試方法或setUp() 期間調用此項跳過當前測試。有關詳細信息,請參閱跳過測試和預期失敗。
3.1 新版功能.
**subTest(msg=None, params)
返回作為子測試執行封閉代碼塊的上下文管理器。msg和params是可選的任意值,每當子測試失敗時都會顯示這些值,允許您清楚地識別它們。
測試用例可以包含任意數量的子測試聲明,並且它們可以任意嵌套。
有關詳細信息,請參閱使用子測試區分測試迭代。
3.4 新版功能.
debug()
在不收集結果的情況下運行測試。這允許將測試提出的異常傳播到調用方,並可用於支持在調試器下運行測試。
TestCase類提供了幾種用於檢查和報告失敗的斷言方法。下表列出了最常用的方法(有關更多斷言方法,請參閱下表):
Method | Checks that | New in |
---|---|---|
assertEqual(a, b) | a == b | |
assertNotEqual(a, b) | a != b | |
assertTrue(x) | bool(x) is True | |
assertFalse(x) | bool(x) is False | |
assertIs(a, b) | a is b | 3.1 |
assertIsNot(a, b) | a is not b | 3.1 |
assertIsNone(x) | x is None | 3.1 |
assertIsNotNone(x) | x is not None | 3.1 |
assertIn(a, b) | a in b | 3.1 |
assertNotIn(a, b) | a not in b | 3.1 |
assertIsInstance(a, b) | isinstance(a, b) | 3.2 |
assertNotIsInstance(a, b) | not isinstance(a, b) | 3.2 |
所有斷言方法都接受msg參數,如果指定該參數,則用作失敗時的錯誤消息(另請參閱 longMesage)。請注意,msg關鍵字參數可以傳遞到斷言Raises(),斷言RaisesRegex(),斷言Warns(),斷言WarnsRegex()只有在它們用作上下文管理器時。
assertEqual(first, second, msg=None)
測試第一個和第二個相等。如果值不相等比較,則測試將失敗。
此外,如果第一和第二類型與列表、元組、命令、集、凍結集或 str 或子類寄存器與addTypeEqualityFunc()的任何類型完全相同,則將調用特定於類型的相等函數,以便生成更有用的默認錯誤消息(另請參閱類型特定方法的列表)。
在版本 3.1 中更改:添加了類型特定的相等函數的自動調用。
在版本 3.2 中更改:斷言多林平等()添加為用於比較字符串的默認類型相等函數。
assertNotEqual(first, second, msg=None)
測試第一個和第二個不相等。如果值比較相等,則測試將失敗。
assertTrue(expr, msg=None)
assertFalse(expr, msg=None)
測試expr 是否為 true(或 false)。
請注意,這等效於 而不是(用於后者)。當有更具體的方法可用時,也應避免使用此方法(例如, 而不是 ,因為它們在發生故障時提供了更好的錯誤消息。bool(expr) is Trueexpr is TrueassertIs(expr, True)assertEqual(a, b)assertTrue(a == b)
assertIs(first, second, msg=None)
assertIsNot(first, second, msg=None)
測試第一個和第二個計算(或不計算)到同一個對象。
3.1 新版功能.
assertIsNone(expr, msg=None)
assertIsNotNone(expr, msg=None)
測試expr是(或不是)None。
3.1 新版功能.
assertIn(member, container, msg=None)
assertNotIn(member, container, msg=None)
測試該成員在(或不在)容器中。
3.1 新版功能.
assertIsInstance(obj, cls, msg=None)
assertNotIsInstance(obj, cls, msg=None)
測試obj是(或不是)cls的實例(可以是類或類元組,如isinstance()支持的)。要檢查確切的類型,請使用斷言(type(obj),cls。
3.2 新版功能.
還可以使用以下方法檢查異常、警告和日志消息的產生:
Method | Checks that | New in |
---|---|---|
assertRaises(exc, fun, *args, **kwds) | fun(*args, **kwds) raises exc | |
assertRaisesRegex(exc, r, fun, *args, **kwds) | fun(*args, **kwds) raises exc and the message matches regex r | 3.1 |
assertWarns(warn, fun, *args, **kwds) | fun(*args, **kwds) raises warn | 3.2 |
assertWarnsRegex(warn, r, fun, *args, **kwds) | fun(*args, **kwds) raises warn and the message matches regex r | 3.2 |
assertLogs(logger, level) | The with block logs on logger with minimum level | 3.4 |
assertRaises(exception, callable, *args, **kwds)
assertRaises(exception, *, msg=None)
測試當可調用時使用也傳遞給assertRaises()
的任何位置參數或關鍵字參數調用異常時是否引發異常。如果引發異常,則通過測試;如果引發另一個異常,則通過測試;如果未引發異常,則測試失敗。若要捕獲一組異常中的任何一個,可以傳遞包含異常類的元組作為異常傳遞。
如果只給出異常和可能給出msg參數,則返回上下文管理器,以便測試的代碼可以內聯編寫,而不是作為函數編寫:
with self.assertRaises(SomeException):
do_something()
當用作上下文管理器時,assertRaises()接受附加關鍵字參數msg。
上下文管理器將捕獲的異常對象存儲在其屬性中。如果意圖對引發異常執行其他檢查,則此功能非常有用:exception
with self.assertRaises(SomeException) as cm:
do_something()
the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)
在版本 3.1 中更改:添加了使用斷言() 作為上下文管理器的能力。
在版本 3.2 中更改:添加了該屬性。exception
在版本 3.3 中更改:用作上下文管理器時添加了 msg 關鍵字參數。
assertRaisesRegex(exception, regex, callable, *args, **kwds)
assertRaisesRegex(exception, regex, *, msg=None)
與斷言()一樣,但也測試正則表達式在引發異常的字符串表示形式上匹配。正則表達式可能是正則表達式對象或包含適合re.search() 使用的正則表達式的字符串。例子:
self.assertRaisesRegex(ValueError, "invalid literal for.*XYZ'$",
int, 'XYZ')
或者:
with self.assertRaisesRegex(ValueError, 'literal'):
int('XYZ')
版本 3.1 中的新功能:在名稱下添加。assertRaisesRegexp
在版本 3.2 中更改:重命名為斷言RaisesRegex()。
在版本 3.3 中更改:用作上下文管理器時添加了 msg 關鍵字參數。
assertWarns(warning, callable, *args, **kwds)
assertWarns(warning, *, msg=None)
測試當可調用時使用也傳遞給assertWarns()的任何位置參數或關鍵字參數調用時觸發警告。如果觸發警告,測試通過;如果警告沒有觸發,則測試失敗。任何異常都是錯誤。要捕獲任何一組警告,可以傳遞包含警告類的元組作為警告。
如果只給出警告和msg參數,則返回上下文管理器,以便測試的代碼可以內聯編寫,而不是作為函數編寫:
with self.assertWarns(SomeWarning):
do_something()
當用作上下文管理器時,斷言警告()接受附加關鍵字參數msg。
上下文管理器將捕獲的警告對象存儲在其屬性中,以及觸發 和 屬性中觸發警告的源行。如果意圖對捕獲的警告執行其他檢查,這非常有用:warningfilenamelineno
with self.assertWarns(SomeWarning) as cm:
do_something()
self.assertIn('myfile.py', cm.filename)
self.assertEqual(320, cm.lineno)
此方法在調用時無論警告篩選器是否就位,都有效。
版本 3.2 中的新版本。
在版本 3.3 中更改:用作上下文管理器時添加了 msg 關鍵字參數。
assertWarnsRegex(warning, regex, callable, *args, **kwds)
assertWarnsRegex(warning, regex, *, msg=None)
與斷言警告()一樣,但也測試正則表達式在觸發警告的消息上匹配。正則表達式可能是正則表達式對象或包含適合re.search() 使用的正則表達式的字符串。例子:
self.assertWarnsRegex(DeprecationWarning,
r'legacy_function\(\) is deprecated',
legacy_function, 'XYZ')
或者:
with self.assertWarnsRegex(RuntimeWarning, 'unsafe frobnicating'):
frobnicate('/etc/passwd')
3.2 新版功能.
在版本 3.3 中更改:用作上下文管理器時添加了 msg 關鍵字參數。
assertLogs(logger=None, level=None)
上下文管理器,以測試至少一條消息記錄器或其子級之一,至少具有給定級別。
如果給定,記錄器應為日志記錄。記錄器對象或提供記錄器名稱的 str。默認值是根記錄器,它將捕獲所有消息。
如果給定,級別應為數字日志記錄級別或其字符串等效級別(例如 或 )。默認值為 。"ERROR"logging.ERRORlogging.INFO
如果塊內發出的至少一條消息與記錄器和級別條件匹配,則測試通過,否則失敗。with
上下文管理器返回的對象是記錄幫助程序,用於保留匹配日志消息的跟蹤。它有兩個屬性:
records
日志記錄的列表。匹配日志消息的日志記錄對象。
output
具有匹配消息的格式化輸出的str對象的列表。
示例:
with self.assertLogs('foo', level='INFO') as cm:
logging.getLogger('foo').info('first message')
logging.getLogger('foo.bar').error('second message')
self.assertEqual(cm.output, ['INFO:foo:first message',
'ERROR:foo.bar:second message'])
3.4 新版功能.
還有其他方法用於執行更具體的檢查,例如:
方法 | 示例 | 新增版本 |
---|---|---|
assertAlmostEqual(a, b) | round(a-b, 7) == 0 | |
assertNotAlmostEqual(a, b) | round(a-b, 7) != 0 | |
assertGreater(a, b) | a > b | 3.1 |
assertGreaterEqual(a, b) | a >= b | 3.1 |
assertLess(a, b) | a < b | 3.1 |
assertLessEqual(a, b) | a <= b | 3.1 |
assertRegex(s, r) | r.search(s) | 3.1 |
assertNotRegex(s, r) | not r.search(s) | 3.2 |
assertCountEqual(a, b) | a and b have the same elements in the same number, regardless of their order. | 3.2 |
assertAlmostEqual(first, second, places=7, msg=None, delta=None)
assertNotAlmostEqual(first, second, places=7, msg=None, delta=None)
通過計算差值、舍入到給定的十進制位數(默認值 7)和與零進行比較來測試第一個和第二個大致相等(或不大致)相等。請注意,這些方法將值舍入到給定的十進制位數(即如舍入()函數)而不是有效數字。
如果提供增量而不是地點,則第一和第二之間的差值必須小於或等於(或大於)增量。
供應三角洲和地方提出了一個類型Error。
在版本 3.2 中更改:斷言AlmostEqual()會自動考慮幾乎相等的比較相等的對象。斷言非同方()自動失敗,如果對象比較相等。添加了增量關鍵字參數。
assertGreater(first, second, msg=None)
assertGreaterEqual(first, second, msg=None)
assertLess(first, second, msg=None)
assertLessEqual(first, second, msg=None)
Test that first is respectively >, >=, < or <= than second depending on the method name. If not, the test will fail:
>>>
>>> self.assertGreaterEqual(3, 4)
AssertionError: "3" unexpectedly not greater than or equal to "4"
3.1 新版功能.
assertRegex(text, regex, msg=None)
assertNotRegex(text, regex, msg=None)
測試正則表達式搜索是否匹配(或不匹配)文本。如果發生故障,錯誤消息將包括模式和文本(或模式和文本意外匹配的部分)。正則表達式可能是正則表達式對象或包含適合re.search() 使用的正則表達式的字符串。
版本 3.1 中的新功能:在名稱下添加。assertRegexpMatches
在版本 3.2 中更改:該方法已重命名為斷言Regex()。assertRegexpMatches()
版本 3.2 中的新版本:斷言無Regex()。
版本 3.5 中的新功能:名稱是斷言NotRegex() 的棄用別名。assertNotRegexpMatches
assertCountEqual(first, second, msg=None)
測試該序列首先包含與第二個相同的元素,而不管它們的順序如何。如果它們沒有,將生成一條錯誤消息,列出序列之間的差異。
比較第一個和第二個元素時,不會忽略重復元素。它驗證每個元素在兩個序列中是否具有相同的計數。等效於 :但也適用於不可ashash 的對象的序列。assertEqual(Counter(list(first)), Counter(list(second)))
版本 3.2 中的新版本。
斷言平等() 方法將相同類型對象的相等性檢查調度到不同的類型特定方法。這些方法已經實現為大多數內置類型,但也可以注冊新方法使用addTypeEqualityFunc():
addTypeEqualityFunc(typeobj, function)
注冊由assertEqual() 調用的類型特定方法,以檢查兩個類型obj(非子類)的對象是否比較相等。函數必須具有兩個位置參數和第三個 msg=None 關鍵字參數,就像斷言平等() 一樣。當檢測到前兩個參數之間的不等式時,它必須提高自我.failureException(msg)——可能提供有用的信息,並在錯誤消息中詳細解釋不等式。
3.1 新版功能.
斷言Equal()自動使用的類型特定方法的列表總結如下表。請注意,通常不需要直接調用這些方法。
方法 | 用於比較 | 新增版本 |
---|---|---|
assertMultiLineEqual(a, b) | strings | 3.1 |
assertSequenceEqual(a, b) | sequences | 3.1 |
assertListEqual(a, b) | lists | 3.1 |
assertTupleEqual(a, b) | tuples | 3.1 |
assertSetEqual(a, b) | sets or frozensets | 3.1 |
assertDictEqual(a, b) | dicts | 3.1 |
assertMultiLineEqual(first, second, msg=None)
測試多行字符串是否等於字符串第二。如果不等於,則突出顯示差異的兩個字符串的差異將包含在錯誤消息中。默認情況下,在將字符串與斷言平等() 進行比較時,此方法是使用。
3.1 新版功能.
assertSequenceEqual(first, second, msg=None, seq_type=None)
測試兩個序列相等。如果seq_type,則第一和第二個都必須是seq_type否則將引發故障。如果序列不同,則構造一條錯誤消息,顯示兩者之間的差異。
此方法不是由斷言質量() 直接調用的,但它用於實現斷言列表qual() 和斷言三等()。
3.1 新版功能.
assertListEqual(first, second, msg=None)
assertTupleEqual(first, second, msg=None)
測試兩個列表或元組相等。如果沒有,則構造一條錯誤消息,僅顯示兩者之間的差異。如果任一參數的類型錯誤,也會引發錯誤。默認情況下,當將列表或元組與斷言Equal() 進行比較時,使用這些方法。
3.1 新版功能.
assertSetEqual(first, second, msg=None)
測試兩組相等。如果沒有,則構造一條錯誤消息,列出集之間的差異。默認情況下,在將集或凍結集與斷言平等() 進行比較時,此方法是使用。
如果第一個或第二個方法沒有方法,則失敗。set.difference()
3.1 新版功能.
assertDictEqual(first, second, msg=None)
測試兩個字典是否相等。如果沒有,將構造一條錯誤消息,顯示字典中的差異。默認情況下,此方法將用於比較調用中的字典,以斷言平等()。
3.1 新版功能.
最后,測試用例提供了以下方法和屬性:
fail(msg=None)
無條件地使用 msg或錯誤消息發出測試失敗信號。None
failureException
此類屬性提供測試方法引發異常。如果測試框架需要使用專用異常(可能攜帶其他信息),則必須將此異常子分類,以便對框架"公平"。此屬性的初始值為斷言Error。
longMessage
此類屬性確定當自定義失敗消息作為 msg 參數傳遞到失敗的 assertXYY 調用時會發生什么情況。 是默認值。在這種情況下,自定義消息將追加到標准失敗消息的末尾。當設置為 時,自定義消息將替換標准消息。TrueFalse
可以通過將實例屬性 self.longMessage 分配給或調用斷言方法之前在單個測試方法中重寫類設置。TrueFalse
類設置在每次測試調用之前重置。
3.1 新版功能.
maxDiff
此屬性通過報告失敗差異的斷言方法控制差異輸出的最大長度。它默認為 80*8 個字符。受此屬性影響的斷言方法為斷言序列平等()(包括委托給它的所有序列比較方法)、斷言DictEqual() 和斷言MultiLineEqual()。
設置為 表示沒有差異的最大長度。maxDiffNone
版本 3.2 中的新版本。
測試框架可以使用以下方法來收集有關測試的信息:
countTestCases()
返回此測試對象表示的測試數。對於TestCase實例,這始終為 。1
defaultTestResult()
返回應用於此測試用例類的測試結果類的實例(如果沒有向run() 方法提供其他結果實例)。
對於TestCase實例,這始終是TestResult 的實例;測試用例的子類應覆蓋此項。
id()
返回標識特定測試用例的字符串。這通常是測試方法的全名,包括模塊和類名。
shortDescription()
返回測試的說明,或者未提供說明。此方法的默認實現返回測試方法的文檔字符串(如果可用)或 的第一行。NoneNone
在版本 3.1 中更改:在 3.1 中,這被更改以將測試名稱添加到簡短描述中,即使在存在文檔字符串的情況下。這就導致與單元測試擴展的兼容性問題,並且將測試名稱添加到 Python 3.2中的TextTest 結果。
addCleanup(function, *args, **kwargs)
此方法在拆解() 之后或設置組()后無條件調用,如果setUp()引發異常。
它負責調用通過addCleanup() 添加的所有清理函數。如果您需要在拆解()之前調用清理函數,那么您可以自己調用doCleanups()。
doCleanups()將方法一次從清理函數堆棧中彈出,因此可以隨時調用它。
3.1 新版功能.
doCleanups()
此方法在拆解() 之后或設置組()后無條件調用,如果setUp()引發異常。
它負責調用通過addCleanup() 添加的所有清理函數。如果您需要在拆解()之前調用清理函數,那么您可以自己調用doCleanups()。
doCleanups()將方法一次從清理函數堆棧中彈出,因此可以隨時調用它。
3.1 新版功能.
classmethod addClassCleanup(function, /, *args, **kwargs)
添加在拆解類() 后調用的函數來清理測試類中使用的資源。函數將按與添加順序相反的順序調用 (LIFO)。在添加它們時,使用傳遞給addClassCleanup() 的任何參數和關鍵字參數來調用它們。
如果setUpClass()失敗,這意味着不調用拆解類(),則仍將調用添加的任何清理函數。
3.8 新版功能.
classmethod doClassCleanups()
此方法在拆解類() 之后或設置的UpClass()引發異常后無條件調用。
它負責調用 中添加的所有清理函數。如果您需要在拆解類()之前調用清理函數,那么您可以調用自己。 addCleanupClass()doCleanupsClass()
doCleanupsClass()一次從清理函數堆棧中彈出方法,因此可以隨時調用它。
3.8 新版功能.
class unittest.IsolatedAsyncioTestCase(methodName='runTest')
此類提供類似於 TestCase 的API,並接受作為測試函數的coroutine。
3.8 新版功能.
coroutine asyncSetUp()
為准備測試夾具而調用的方法。這在 調用后。在調用測試方法之前,立即調用此調用;除了斷言錯誤或跳過測試之外,此方法引發的任何異常都將被視為錯誤而不是測試失敗。默認實現不執行任何操作。setUp()
coroutine asyncTearDown()
在調用測試方法並記錄結果后立即調用方法。這在 之前調用。即使測試方法引發異常,也調用此選項,因此子類中的實現可能需要特別小心地檢查內部狀態。此方法引發的任何異常(除斷言錯誤或SkipTest外)將被視為附加錯誤,而不是測試失敗(從而增加報告錯誤的總數)。只有在異步集()成功時,無論測試方法的結果如何,都將調用此方法。默認實現不執行任何操作。tearDown()
addAsyncCleanup(function, /, *args, **kwargs)
此方法接受可用作清理函數的Coroutine。
run(result=None)
設置一個新的事件循環來運行測試,將結果收集到作為結果通過的測試結果對象中。如果省略結果或 ,則創建臨時結果對象(通過調用 方法)並使用。將結果對象返回到run() 的調用方。在測試結束時,事件循環中的所有任務將被取消。NonedefaultTestResult()
說明訂單的示例:
from unittest import IsolatedAsyncioTestCase
events = []
class Test(IsolatedAsyncioTestCase):
def setUp(self):
events.append("setUp")
async def asyncSetUp(self):
self._async_connection = await AsyncConnection()
events.append("asyncSetUp")
async def test_response(self):
events.append("test_response")
response = await self._async_connection.get("https://example.com")
self.assertEqual(response.status_code, 200)
self.addAsyncCleanup(self.on_cleanup)
def tearDown(self):
events.append("tearDown")
async def asyncTearDown(self):
await self._async_connection.close()
events.append("asyncTearDown")
async def on_cleanup(self):
events.append("cleanup")
if __name__ == "__main__":
unittest.main()
運行測試后,將包含 。events["setUp", "asyncSetUp", "test_response", "asyncTearDown", "tearDown", "cleanup"]
FunctionTestCase類
class unittest.FunctionTestCase(testFunc, setUp=None, tearDown=None, description=None)
此類實現TestCase 接口的部分,該部分允許測試運行程序驅動測試,但不提供測試代碼可用於檢查和報告錯誤的方法。這用於使用舊式測試代碼創建測試用例,允許將它集成到基於單元測試的測試框架中。
用例組織
TestSuite類
class unittest.TestSuite(tests=())
此類表示單個測試用例和測試套件的聚合。該類提供測試運行程序所需的接口,以允許它作為任何其他測試用例運行。運行TestSuite實例與在套件上遍機相同,單獨運行每個測試。
如果提供了測試,它必須是單個測試用例或其他測試套件的可重復性,這些測試用例或最初將用於構建套件。提供了其他方法,以稍后將測試用例和套件添加到集合中。
TestSuite對象的行為與TestCase對象非常類似,只是它們實際上不實現測試。相反,它們用於將測試聚合到應一起運行的測試組中。一些其他方法可用於將測試添加到TestSuite實例:
addTest(test)
向套件添加測試用例或測試套件。
addTests(tests)
將可重復的 TestCase 和TestSuite實例的所有測試添加到此測試套件中。
這相當於在測試中進行遍溯,為每個元素調用 addTest()。
TestSuite與TestCase 共享以下方法:
run(result)
運行與此套件關聯的測試,將結果收集到測試結果對象中,以結果傳遞給。請注意,與TestCase.run() 不同,TestSuite.run()要求將結果對象傳遞。
debug()
在不收集結果的情況下運行與此套件關聯的測試。這允許將測試提出的異常傳播到調用方,並可用於支持在調試器下運行測試。
countTestCases()
返回此測試對象表示的測試數,包括所有單獨的測試和子套件。
iter()
由TestSuite 分組的測試始終通過迭代進行訪問。子類可以通過重寫__iter__() 來懶洋洋地提供測試。請注意,此方法可能在單個套件上多次調用(例如,在計算測試或比較相等性時),因此,在 TestSuite.run() 之前重復迭代返回的測試對於每個調用迭代必須相同。在TestSuite.run() 之后,調用方不應依賴此方法返回的測試,除非調用方使用重寫的子類來保留測試引用。TestSuite._removeTestAtIndex()
在版本 3.2 中更改:在較早的版本中,TestSuite直接訪問測試,而不是通過__iter__訪問,因此重寫 iter()不足以提供測試。
在版本 3.4 中更改:在較早的版本中,TestSuite在TestSuite.run() 之后對每個測試用例進行了引用。 子類可以通過重寫 來還原該行為。TestSuite._removeTestAtIndex()
在TestSuite 對象的典型用法中,run()方法由 一個而不是最終用戶測試工具調用。TestRunner
用例加載及運行
TestLoader類
class unittest.TestLoader
加載測試時遇到的非致命錯誤的列表。任何點都不由加載器重置。致命錯誤由相關的方法發出信號,向調用方引發異常。非致命錯誤也由綜合測試指示,該測試將在運行時引發原始錯誤。
3.5 新版功能.
測試加載器對象具有以下方法:
errors
加載測試時遇到的非致命錯誤的列表。任何點都不由加載器重置。致命錯誤由相關的方法發出信號,向調用方引發異常。非致命錯誤也由綜合測試指示,該測試將在運行時引發原始錯誤。
3.5 新版功能.
測試加載器對象具有以下方法:
loadTestsFromTestCase(testCaseClass)
返回 TestCase 派生中包含的所有測試用例的套件。testCaseClass
為 getTestCaseNames() 命名的每個方法創建一個測試用例實例。默認情況下,這些是以 開頭的方法名稱。如果getTestCaseNames()不返回任何方法,但該方法已實現,則改為為該方法創建單個測試用例。testrunTest()
loadTestsFromModule(module, pattern=None)
返回給定模塊中包含的所有測試用例套件。此方法搜索模塊中派生自TestCase 的類,並為為類定義的每個測試方法創建類的實例。
注意:雖然在共享固件和幫助器函數時,使用 TestCase 派生類的層次結構可能很方便,但定義不直接實例化的基類的測試方法對此方法沒有很好的作用。但是,當夾具不同且在子類中定義時,這樣做非常有用。
如果模塊提供函數,將調用它來加載測試。這允許模塊自定義測試加載。這是load_tests協議。模式參數作為 第三個參數傳遞到 。load_testsload_tests
在版本 3.2 中更改:支持添加。load_tests
在版本 3.5 中更改:未記錄的和非官方use_load_tests參數被棄用和忽略,盡管它仍然被接受為向后兼容性。該方法現在還接受作為第三個參數傳遞給的關鍵字參數模式。load_tests
loadTestsFromName(name, module=None)
返回給定字符串說明符的所有測試用例的套件。
指定名稱是一個"虛名",可以解析為模塊、測試用例類、測試用例類中的測試方法、TestSuite 實例或返回TestCase或TestSuite實例的可調用對象。這些檢查按此處列出的順序應用;也就是說,可能測試用例類上的方法將被拾取為"測試用例類中的測試方法",而不是"可調用對象"。
例如,如果您有一個模塊包含具有三種測試方法 (, 和) 的TestCase派生類,則說明符將導致此方法返回將運行所有三種測試方法的套件。使用指定程序將導致它返回僅運行測試方法的測試套件。說明符可以引用尚未導入的模塊和包;它們將被導入作為副作用。SampleTestsSampleTestCasetest_one()test_two()test_three()'SampleTests.SampleTestCase''SampleTests.SampleTestCase.test_two'test_two()
方法可以選擇解析相對於給定模塊的名稱。
在版本 3.5 中更改:如果在遍歷名稱時發生了ImportError或 屬性錯誤,則將在運行時引發該錯誤的綜合測試。這些錯誤包含在 self.錯誤累積的錯誤中。
loadTestsFromNames(names, module=None)
與loadTestsFromName()類似,但采用一系列名稱而不是單個名稱。返回值是一個測試套件,它支持為每個名稱定義的所有測試。
getTestCaseNames(testCaseClass)
與loadTestsFromName()類似,但采用一系列名稱而不是單個名稱。返回值是一個測試套件,它支持為每個名稱定義的所有測試。
discover(start_dir, pattern='test*.py', top_level_dir=None)
通過從指定的開始目錄重復到子目錄來查找所有測試模塊,並返回包含這些模塊的 TestSuite 對象。將僅加載與模式匹配的測試文件。(使用 shell 樣式模式匹配。將只加載可導入的模塊名稱(即有效的 Python 標識符)。
所有測試模塊都必須從項目的頂層導入。如果 start 目錄不是頂級目錄,則必須單獨指定頂級目錄。
如果導入模塊失敗(例如由於語法錯誤),則這將被記錄為單個錯誤,並且發現將繼續。如果導入失敗是由於引發 SkipTest,它將記錄為跳過而不是錯誤。
如果找到包(包含名為 )的文件目錄),將檢查該包是否為函數。如果存在,則將調用 。測試發現需要注意確保包在調用期間只檢查一次測試,即使load_tests函數本身調用。init.pyload_testspackage.load_tests(loader, tests, pattern)loader.discover
如果存在,則發現不會重復到包中,則負責加載包中的所有測試。load_testsload_tests
該模式故意不存儲為加載器屬性,以便包可以繼續發現本身。top_level_dir存儲,因此不需要將此參數傳遞給 。load_testsloader.discover()
start_dir可以是虛線模塊名稱以及目錄。
版本 3.2 中的新版本。
在版本 3.4 中更改:在導入時引發 SkipTest的模塊將記錄為跳過,而不是錯誤。發現適用於命名空間包。路徑在導入之前進行排序,以便執行順序相同,即使基礎文件系統的順序不依賴於文件名。
在版本 3.5 中更改:現在檢查找到的包,而不管其路徑是否與模式匹配,因為包名稱不可能與默認模式匹配。load_tests
測試加載器的以下屬性可以通過子類或實例上的賦值進行配置:
testMethodPrefix
字符串提供將被解釋為測試方法的方法名稱的前綴。默認值為 。'test'
這會影響getTestCaseNames()和所有方法。loadTestsFrom*()
sortTestMethodsUsing
在getTestCaseNames() 和所有方法中對方法名稱進行排序時,用於比較方法名稱的函數。loadTestsFrom*()
suiteClass
從測試列表中構造測試套件的可調用對象。不需要對生成的對象使用任何方法。默認值是TestSuite 類。
這會影響所有方法。loadTestsFrom*()
testNamePatterns
測試方法必須匹配才能包含在測試套件中的 Unix shell 樣式通配符名稱模式的列表(請參閱選項)。-v
如果此屬性不是(默認值),則測試套件中包含的所有測試方法必須匹配此列表中的一個模式。請注意,匹配始終使用fnmatch.fnmatchcase()執行,因此與傳遞給選項的模式不同,必須使用通配符轉換簡單的子字符串模式。None-v*
這會影響所有方法。loadTestsFrom*()
3.7 新版功能.
TestResult類
class unittest.TestResult
此類用於編譯有關哪些測試已成功和哪些測試失敗的信息。
測試結果對象存儲一組測試的結果。測試案例和測試設置類可確保正確記錄結果;測試作者無需擔心記錄測試結果。
在單元測試之上構建的測試框架可能希望訪問通過運行一組測試來報告目的生成的TestResult對象; a 測試結果實例由 方法為此返回。TestRunner.run()
測試結果實例具有以下屬性,在檢查運行一組測試的結果時,這些屬性將感興趣:
errors
包含 2 元數的TestCase實例和字符串保存格式化的回溯的列表。每個元組表示引發意外異常的測試。
failures
包含 2 元數的TestCase實例和字符串保存格式化的回溯的列表。每個元組表示使用方法顯式發出故障信號的測試。TestCase.assert*()
skipped
包含 2 個 tup 的TestCase實例和字符串的列表,其中包含跳過測試的原因。
3.1 新版功能.
expectedFailures
包含 2 元數的TestCase實例和字符串保存格式化的回溯的列表。每個元組表示測試用例的預期失敗。
unexpectedSuccesses
包含TestCase 實例的列表,這些實例被標記為預期失敗,但成功。
shouldStop
設置為何時執行測試應停止停止()。True
testsRun
到目前為止運行的測試總數。
buffer
如果設置為 true,並且將在調用的startTest() 和 stopTest() 之間進行緩沖。收集的輸出將只回顯到實際,如果測試失敗或錯誤。任何輸出也附加到失敗/錯誤消息。sys.stdoutsys.stderrsys.stdoutsys.stderr
版本 3.2 中的新版本。
failfast
如果設置為 true stop(),將在第一次失敗或錯誤時調用,則停止測試運行。
3.2 新版功能.
tb_locals
如果設置為 true,則局部變量將顯示在回溯中。
3.5 新版功能.
wasSuccessful()
如果到目前為止運行的所有測試都通過,則返回 ,否則返回 。TrueFalse
在版本 3.4 中更改:如果使用預期失敗()修飾器標記的測試出現任何意外成功,則返回。False
stop()
可以通過將 "應該停止"屬性設置為 來調用此方法來表示正在運行的測試集應中止。 對象應尊重此標志並返回而不運行任何其他測試。TrueTestRunner
例如,當用戶從鍵盤發出中斷信號時,TextTestRunner類使用此功能來停止測試框架。提供實現的交互式工具可以以類似的方式使用。TestRunner
TestResult 類的以下方法用於維護內部數據結構,並可以擴展為子類以支持其他報告要求。這在構建在運行測試時支持交互式報告的工具時特別有用。
startTest(test)
在測試用例測試即將運行時調用。
stopTest(test)
無論是否執行測試用例測試后調用。
startTestRun()
在執行任何測試之前調用一次。
3.1 新版功能.
stopTestRun()
執行所有測試后調用一次。
3.1 新版功能.
addError(test, err)
當測試用例測試引發意外異常時調用。錯誤是sys. exc_info () 的表格的元組。(type, value, traceback)
默認實現將元組追加到實例的錯誤屬性中,其中 formatted_err從 err 派生的格式化回溯。(test, formatted_err)
addFailure(test, err)
當測試用例測試發出故障信號時調用。錯誤是sys. exc_info () 的表格的元組。(type, value, traceback)
默認實現將元組追加到實例的故障屬性中,其中 formatted_err從 err 派生的格式化回溯。(test, formatted_err)
addSuccess(test)
測試用例測試成功時調用。
默認實現不執行任何操作。
addSkip(test, reason)
跳過測試用例測試時調用。原因是測試給出跳過的原因。
默認實現將元組追加到實例跳過的屬性。(test, reason)
addExpectedFailure(test, err)
在測試用例測試失敗時調用,但用預期的失敗() 修飾器標記。
默認實現將元組追加到實例的預期Failures屬性中,formatted_err從 err 派生的格式化回溯。(test, formatted_err)
addUnexpectedSuccess(test)
在測試用例測試標記為預期失敗() 修飾器時調用,但成功。
默認實現將測試追加到實例的意外成功屬性。
addSubTest(test, subtest, outcome)
子測試結束時調用。測試是與測試方法對應的測試用例。子測試是描述子測試的自定義測試用例實例。
如果結果是"無",則子測試成功。否則,它失敗,但結果為 sys.exc_info: 返回的窗體的元組。(type, value, traceback)
當結果成功時,默認實現不執行任何操作,並且將子測試失敗記錄為正常失敗。
3.4 新版功能.
TextTestResult類
class unittest.TextTestResult(stream, descriptions, verbosity)
文本測試運行者使用的測試結果的具體實現。
版本 3.2 中的新功能:此類以前名為 。舊名稱仍作為別名存在,但已棄用。_TextTestResult
defaultTestLoader對象
unittest.defaultTestLoader
要共享的測試加載器類的實例。如果不需要對 TestLoader 進行自定義,則可以使用此實例,而不是重復創建新實例。
TextTestRunner類
class unittest.TextTestRunner(stream=None, descriptions=True, verbosity=1, failfast=False, buffer=False, resultclass=None, warnings=None, *, tb_locals=False)
將結果輸出到流的基本測試流道實現。如果流為 ,則默認 sys.stderr用作輸出流。此類有幾個可配置的參數,但本質上非常簡單。運行測試套件的圖形應用程序應提供備用實現。當功能添加到單元測試時,此類實現應接受為構造流道更改的接口。None**kwargs
默認情況下,此運行程序顯示棄用警告、待定預測警告、資源警告和導入警告,即使默認情況下它們被忽略。棄用單元測試方法導致的棄用警告也是特例,當警告篩選器為 或 時,它們每個模塊只會出現一次,以避免警告消息太多。可以使用 Python 或選項(請參閱警告控件)重寫此行為,並將警告留給。'default''always'-Wd-WaNone
在版本 3.2 中更改:添加了參數。warnings
在版本 3.2 中更改:默認流在實例化時間設置為 sys.stderr,而不是導入時間。
在版本 3.5 中更改:添加了tb_locals參數。
_makeResult()
此方法返回由run()使用的實例。它不打算直接調用,但可以在子類中重寫以提供自定義 。TestResultTestResult
_makeResult()實例化在構造函數中傳遞的類或可調用的類作為參數。如果提供"否",則默認為 TextTest結果。結果類使用以下參數實例化:TextTestRunnerresultclassresultclass
stream, descriptions, verbosity
run(test)
This method is the main public interface to the TextTestRunner. This method takes a TestSuite or TestCase instance. A TestResult is created by calling _makeResult() and the test(s) are run and the results printed to stdout.
unittest.main
unittest.main(module='__main__', defaultTest=None, argv=None, testRunner=None, testLoader=unittest.defaultTestLoader, exit=True, verbosity=1, failfast=None, catchbreak=None, buffer=None, warnings=None)
一個命令行程序,從模塊加載一組測試並運行它們;這主要用於使測試模塊便於執行。此函數的最簡單用途是在測試腳本末尾包含以下行:
if __name__ == '__main__':
unittest.main()
您可以通過傳遞詳細參數來運行具有更多詳細信息的測試:
if __name__ == '__main__':
unittest.main(verbosity=2)
默認值Test參數是單個測試的名稱,或者是要運行的測試名稱的可重復,如果未通過argv指定測試名稱。如果未指定或未通過argv提供測試名稱,則模塊中找到的所有測試都運行。None
argv參數可以是傳遞給程序的選項列表,第一個元素是程序名稱。如果未指定 或 ,則使用sys.argv的值。None
testRunner參數可以是測試運行程序類,也可以是已創建的實例。默認情況下調用sys.exit(),其退出代碼指示測試運行成功或失敗。main
測試Loader參數必須為測試加載器實例,並默認為默認測試加載器。
main支持通過傳遞參數從交互式解釋器使用 。這會在標准輸出上顯示結果,而不調用sys.exit():exit=False
>>>
>>> from unittest import main
>>> main(module='test_module', exit=False)
故障快、catchbreak 和緩沖區參數的效果與同名命令行選項相同。
警告參數指定在運行測試時應使用的警告篩選器。如果未指定,則如果選項傳遞到 python(請參閱警告控件),它將保留,否則它將設置為 。None-W'default'
調用實際上返回類的實例。這將存儲作為屬性運行的測試的結果。mainTestProgramresult
在版本 3.1 中更改:添加了退出參數。
在版本 3.2 中更改:增加了詳細性、故障快、即入、緩沖和警告參數。
在版本 3.4 中更改:默認測試參數已更改為也接受可重復的測試名稱。
load_tests 協議
3.2 新版功能.
模塊或包可以通過實現名為 的函數自定義在正常測試運行或測試發現期間如何從它們加載測試。load_tests
如果測試模塊定義,它將由TestLoader.loadTestsFromModule() 調用,並具有以下參數:load_tests
load_tests(loader, standard_tests, pattern)
其中模式直接從 中傳遞。它默認為 。loadTestsFromModuleNone
它應該返回一個測試套房。
加載器是執行加載的測試加載器的實例。standard_tests是默認情況下從模塊加載的測試。測試模塊通常只想從標准測試集添加或刪除測試。在加載包作為測試發現的一部分時,使用第三個參數。
從一組特定的 TestCase 類加載測試的典型函數可能看起來像:load_tests
test_cases = (TestCase1, TestCase2, TestCase3)
def load_tests(loader, tests, pattern):
suite = TestSuite()
for test_class in test_cases:
tests = loader.loadTestsFromTestCase(test_class)
suite.addTests(tests)
return suite
如果在包含包的目錄中啟動發現,請從命令行或調用TestLoader.discovery()來檢測 該包。如果該函數不存在,則發現將重復到包中,就像它只是另一個目錄一樣。否則,將最多使用以下參數調用包測試的發現:init.pyload_testsload_tests
load_tests(loader, standard_tests, pattern)
這應返回一個表示包中所有測試的 TestSuite。(將僅包含從 收集的測試。standard_tests__init__.py
因為模式被傳遞到包中可以自由繼續(並可能修改)測試發現。測試包的"不執行任何操作"功能可看起來像:load_testsload_tests
def load_tests(loader, standard_tests, pattern):
# top level directory cached on loader instance
this_dir = os.path.dirname(__file__)
package_tests = loader.discover(start_dir=this_dir, pattern=pattern)
standard_tests.addTests(package_tests)
return standard_tests
在 3.5 版更改:由於無法匹配默認模式的包名稱,Discovery 不再檢查包名稱是否匹配模式。
類及模塊級Fixtures
類和模塊級夾具在TestSuite 中實現。當測試套件遇到來自新類的測試時,則調用上一個類(如果有)的測試,然后是新類的測試。tearDownClass()setUpClass()
同樣,如果測試來自與上一個測試不同的模塊,則運行與上一個模塊的測試,然后是新模塊。tearDownModulesetUpModule
在所有測試都運行到最終並運行之后。tearDownClasstearDownModule
請注意,共享固件不能很好地與 [潛在] 功能(如測試並行化)發揮好,並且它們打破了測試隔離。應小心使用。
單元測試測試加載程序創建的測試的默認順序是將來自同一模塊和類的所有測試分組在一起。這將導致 / (等) 每個類和模塊被調用一次。如果隨機化順序,以便不同模塊和類的測試彼此相鄰,則這些共享固件函數可能在單個測試運行中多次調用。setUpClasssetUpModule
共享夾具不適用於非標准訂購的套件。對於不想支持共享固件的框架,仍然存在。BaseTestSuite
如果在共享固件功能之一期間出現任何異常,則測試報告為錯誤。因為沒有相應的測試實例,所以創建一個對象(與測試案例具有相同的接口)來表示錯誤。如果您只是使用標准單元測試測試運行程序,則此詳細信息並不重要,但如果您是框架作者,則它可能相關。_ErrorHolder
setUpClass和tearDownClass
這些必須實現為類方法:
import unittest
class Test(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls._connection = createExpensiveConnectionObject()
@classmethod
def tearDownClass(cls):
cls._connection.destroy()
如果想要調用 和 基類,則必須自己調用它們。測試用例中的實現為空。setUpClasstearDownClass
如果在 期間引發異常,則類中的測試不運行,並且 不運行 。跳過的類將不具有或運行。如果異常是SkipTest異常,則類將報告為已跳過,而不是錯誤。setUpClasstearDownClasssetUpClasstearDownClass
setUpModule和tearDownModule
應作為函數實現這些功能:
def setUpModule():
createConnection()
def tearDownModule():
closeConnection()
如果在 中引發異常,則模塊中沒有任何測試將運行,並且 不會運行 。如果異常是SkipTest異常,則模塊將報告為已跳過,而不是錯誤。setUpModuletearDownModule
若要添加即使在異常情況下也必須運行的清理代碼,請使用 :addModuleCleanup
unittest.addModuleCleanup(function, /, *args, **kwargs)
添加一個函數,以在測試類期間使用清理資源。函數將按與添加順序相反的順序調用 (LIFO)。在添加它們時,使用傳遞給addModuleCleanup() 的任何參數和關鍵字參數來調用它們。tearDownModule()
如果失敗,這意味着不調用,則仍將調用添加的任何清理函數。setUpModule()tearDownModule()
3.8 新版功能.
unittest.doModuleCleanups()
此函數在 之后或引發異常后無條件調用。tearDownModule()setUpModule()setUpModule()
它負責調用 中添加的所有清理函數。如果需要之前調用清理函數,可以自己調用doModuleCleanups()。 addCleanupModule()tearDownModule()
doModuleCleanups()將方法一次從清理函數堆棧中彈出,因此可以隨時調用它。
3.8 新版功能.
信號量處理
3.2 新版功能.
-c/-catch
命令行選項到單元測試,以及到單元測試.main()的參數,在測試運行期間提供更友好的控制-C 處理。啟用捕獲中斷行為控制-C 將允許當前正在運行的測試完成,然后測試運行將結束並報告到目前為止的所有結果。第二個控件 c 將按通常方式引發鍵盤中斷。catchbreak
Ctrl-C 處理信號處理程序嘗試與安裝自己的信號的代碼或測試保持兼容。SIGINT處理程序。如果處理程序被調用,但不是已安裝的信號。SIGINT處理程序,即已被受測試的系統替換並委派給,然后調用默認處理程序。這通常是替換已安裝的處理程序並將其委托給該處理程序的代碼的預期行為。對於需要禁用控制-c 處理的單個測試,可以使用 removeHandler()修飾器。unittestunittest
框架作者有幾個實用函數,用於在測試框架中啟用 control-c 處理功能。
unittest.installHandler()
設置 Ctrl-C處理程序。當信號。收到SIGINT(通常響應用戶按 Ctrl-C)所有已注冊結果都已調用stop()。
unittest.registerResult(result)
注冊一個測試結果對象以進行Ctrl-C 處理。注冊結果會存儲對它的弱引用,因此它不會阻止對結果進行垃圾回收。
如果未啟用Ctrl-C處理,則注冊 TestResult 對象沒有副作用,因此測試框架可以無條件地注冊它們創建的所有結果,而與是否啟用處理不同。
unittest.removeResult(result)
刪除已注冊的結果。刪除結果后,將不再對該結果對象調用stop()以響應 control-c。
unittest.removeHandler(function=None)
在沒有參數調用時,此函數將刪除Ctrl-C 處理程序(如果已安裝)。此函數還可用作測試修飾器,以在執行測試時臨時刪除處理程序:
@unittest.removeHandler
def test_signal_handling(self):
...