unittest 是Python 自帶的單元測試框架,用它來作單元測試,它裏面封裝好了一些校驗返回的結果方法和一些用例運行前的初始化操做。
官方文檔:https://docs.python.org/3/library/unittest.html#module-unittesthtml
unittest 中有一些類:python
TestCase 測試用例
TestSuite 多個測試用例集合在一塊兒,就是TestSuite
TestLoader 用來加載 TestCase 到 TestSuite 中的
TestRunner 是來運行測試用例的, 測試的結果會保存到 TestResult 實例中,包括運行了多少測試用例,成功了多少,失敗了多少等信息正則表達式
unittest 要求單元測試類必須繼承 unittest.TestCase,該類中的測試方法須要知足以下要求:框架
示例:函數
import unittest class TestFunc(unittest.TestCase): def test_1(self): self.assertEqual(func1(1, 1), 2) def test_2(self): self.assertEqual(func1(1, 2), 3) def func1(a, b): return a + b if __name__ == '__main__': unittest.main()
返回結果:單元測試
.. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK
經常使用的方法:測試
斷言方法 | 檢查條件 |
---|---|
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 |
assertIsNot(a, b) | a is not b |
assertIsNone(x) | x is None |
assertIsNotNone(x) | x is not None |
assertIn(a, b) | a in b |
assertNotIn(a, b) | a not in b |
assertlsInstance(a, b) | isinstance(a, b) |
assertNotIsInstance(a, b) | not isinstance(a, b) |
包含檢查 exceptions, warnings, and log messages 的方法:ui
斷言方法 | 檢查條件 |
---|---|
assertRaises(exc, fun, \*args, \*\*kwds) | fun(\*args, \*\*kwds) raises exc 異常 |
assertRaisesRegex(exc, r, fun, \*args, \*\*kwds) | fun(\*args, \*\*kwds) raises exc 異常,且異常信息匹配正則表達式 r |
assertWarns(warn, fun, \*args, \*\*kwds) | fun(\*args, \*\*kwds) raises warn 警告 |
assertWarnsRegex(warn, r, fun, \*args, \*\*kwds) | fun(\*args, \*\*kwds) raises warn 警告,且異常信息匹配正則表達式 r |
assertLogs(logger, level) | with 語句塊使用日誌器 (logger) 生成 level 級別的日誌 |
包含特定檢查的方法:日誌
斷言方法 | 檢查條件 |
---|---|
assertAlmostEqual(a, b) | round(a-b, 7) == 0 |
assertNotAlmostEqual(a, b) | round(a-b, 7) != 0 |
assertGreater(a, b) | a > b |
assertGreaterEqual(a, b) | a >= b |
assertLess(a, b) | a < b |
assertLessEqual(a, b) | a <= b |
assertRegex(s, r) | r.search(s) |
assertNotRegex(s, r) | not r.search(s) |
assertCountEqual(a, b) | a、b 包含的元素及其數量相同,無視順序 等效於`assertEqual(Counter(list(first)), Counter(list(second)))` |
第一行表示每一個測試用例的運行結果:code
從第一個開始表示相應順序的測試用例運行結果
.
: 測試經過
F
: FAILURE 測試失敗
E
: ERROR 測試出錯
S
: Skip 跳過該測試
以後是錯誤信息 (若是有的話):
示例:
====================================================================== ERROR: test_1 (__main__.TestFunc) ---------------------------------------------------------------------- Traceback (most recent call last): File "test.py", line 30, in func1 raise IndexError IndexError
====================================================================== FAIL: test_2 (__main__.TestFunc) ---------------------------------------------------------------------- Traceback (most recent call last): File "text.py", line 27, in test_2 self.assertEqual(func1(1, 2), 4) AssertionError: 3 != 4
若是是測試出錯,會將錯誤顯示出來
若是是測試失敗,會將失敗緣由以及函數運行的實際結果和指望結果的差別顯示出來
最後是全部測試用例的運行結果:
示例:
---------------------------------------------------------------------- Ran 3 tests in 0.000s FAILED (failures=1, errors=1)
---------------------------------------------------------------------- Ran 3 tests in 0.000s OK
會顯示本次測試一共運行了幾個測試用例,以及運行時間
最後是運行的結果
OK
: 全部測試用例均經過
FAILED
: 沒有所有經過 (以及失敗數量和錯誤數量)
在 TestCase 中有一些特殊的方法:
setUp
: 每一個測試用例以前運行
tearDown
: 每一個測試用例以後運行
setUpClass
: 全部測試用例以前 (setUp) 運行
tearDownClass
: 全部測試用例以後 (tearDown) 運行
運行順序示例:
import unittest class TestFunc(unittest.TestCase): def tearDown(self) -> None: print('from tearDown') def setUp(self) -> None: print('from setUp') @classmethod def tearDownClass(cls) -> None: print('from tearDownClass') @classmethod def setUpClass(cls) -> None: print('from setUpClass') def test_1(self): self.assertEqual(func1(1, 1), 2) def test_2(self): self.assertEqual(func1(1, 2), 3) def func1(a, b): return a + b if __name__ == '__main__': unittest.main()
返回結果
from setUpClass .. from setUp ---------------------------------------------------------------------- from tearDown Ran 2 tests in 0.000s from setUp from tearDown from tearDownClass OK
使用 unittest.main()
會直接運行全部的測試用例,若是但願只運行一些特定的測試用例,就須要用到 TestSuite
類
TestSuite
是許多測試用例的集合,經過 addTest()
方法將測試用例添加到 TestSuite
中
以後實例化一個 TextTestRunner(TestRunner)
類,最後調用 run()
就能夠運行測試用例了
示例:
import unittest from typing import Any # import HTMLTestRunner class MyTestFunc1(unittest.TestCase): def test_1(self): print('from Func1 test_1') self.assertEqual(func1(1, 1), 2) def test_2(self): print('from Func1 test_2') self.assertNotEqual(func1(1, 2), 4) class MyTestFunc2(unittest.TestCase): def test_1(self): print('from Func2 test_1') self.assertTrue(func1(1, 2)) def func1(a, b): return a + b if __name__ == '__main__': test_suite = unittest.TestSuite() test_suite.addTest(unittest.makeSuite(MyTestFunc2)) test_suite.addTest(MyTestFunc1('test_1')) runner = unittest.TextTestRunner() runner.run(test_suite)
返回結果:
.. ---------------------------------------------------------------------- Ran 2 tests in 0.000s OK from Func2 test_1 from Func1 test_1
能夠看出只有 MyTestFunc1 中的 test_1 和 MyTestFunc2 中的 test_1 運行了
而且運行順序取決於添加到 TestSuite 中的順序
經過 TextTestRunner
類能夠將測試結果儲存到文件中,而不是直接打印出來,只須要實例化時傳入相關參數便可
f = open('report.txt', 'w') runner = unittest.TextTestRunner(stream=f)
還有一些其餘的參數,能夠在 TextTestRunner
類源碼中看到
經過其餘模塊能夠獲取其餘格式的測試結果
這些模塊須要單獨安裝 HTMLTestRunner
、xmlrunner
使用方法類似,實例化時傳入必要的參數,以後調用 run()
方法便可