unittest.
TestCase(methodName ='runTest' )
TestCase
類的實例,作為編寫的測試類的基類,具體測試由具體的子類(就是我們寫的測試類)實現。此類實現測試運行程序所需的接口,以使其能夠驅動測試,以及測試代碼可用於檢查和報告各種失敗的方法。
每個TestCase
實例(就是我們寫的測試類)將運行一個基本方法:我們編寫的測試方法。TestCase
實例提供了三組方法:一組用於運行測試,另一組由測試實現用於檢查條件和報告故障,還有一些查詢方法允許收集有關測試本身的信息。
第一組的方法是:
setUp
()
在調用測試方法之前立即調用該方法。除了AssertionError
或SkipTest
之外,此方法引發的任何異常都將被視為錯誤而不是測試失敗。默認實現不執行任何操作。
tearDown
()
調用測試方法並記錄結果后立即調用的方法。即使測試方法引發了異常,也將調用此方法,因此子類中的實現可能需要特別注意檢查內部狀態。除了AssertionError
或SkipTest
之外,此方法引發的任何異常都將被視為錯誤(errors)而不是測試失敗(Failures)。setUp()
無論測試方法的結果如何,僅在成功的情況下才調用此方法(wasSuccessful()==True)。默認實現不執行任何操作。
setUpClass
()
在運行單個類中的測試之前調用的類方法。setUpClass
以類作為唯一參數調用,並且必須修飾為classmethod()
:
@classmethod def setUpClass(cls): ...
tearDownClass
()
與setUpClass原理一致
run
(result = None)
運行測試,將結果收集到TestResult
作為result傳遞的對象中。如果省略result或None
,則創建一個臨時結果對象(通過調用該defaultTestResult()
方法)並使用它。結果對象返回給run()
的調用者。
通過簡單地調用TestCase
實例。
result = TestAdd('test_add1').run()
result = TestAdd('test_chengfa').run()
print(result)
會生成一個測試結果
<unittest.result.TestResult run=1 errors=0 failures=1>
skipTest(reason)
-
@
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()
不會被運行。
def test_chengfa(self): '''測試乘法程序''' self.skipTest('暫不測試') ...
加入后運行,就會跳過
1 2 1 2 1 2 <unittest.runner.TextTestResult run=3 errors=0 failures=0> .s. ---------------------------------------------------------------------- Ran 3 tests in 0.041s OK (skipped=1)
subTest
(msg = None,** params)
可參考unittest單元測試框架教程5-使用subTest進行循環測試
運行測試而不收集結果。這樣可以將測試引發的異常傳播到調用方,並可以用於支持在調試器下運行測試。
result = TestAdd('test_add1').debug() result = TestAdd('test_chengfa').debug() print(result)
運行后會詳細的輸出錯誤信息,便於定位
1 2 Traceback (most recent call last): File "D:\PycharmProjects\untitled\testrunner.py", line 13, in <module> result = TestAdd('test_chengfa').debug() File "C:\Users\MZM\AppData\Local\Programs\Python\Python37-32\lib\unittest\case.py", line 681, in debug getattr(self, self._testMethodName)() File "D:\PycharmProjects\untitled\testmath.py", line 53, in test_chengfa self.assertEqual(resp['data'], self.a * self.b) File "C:\Users\MZM\AppData\Local\Programs\Python\Python37-32\lib\unittest\case.py", line 852, in assertEqual assertion_func(first, second, msg=msg) File "C:\Users\MZM\AppData\Local\Programs\Python\Python37-32\lib\unittest\case.py", line 845, in _baseAssertEqual raise self.failureException(msg) AssertionError: 3 != 2
第二組方法提供了一些斷言方法來檢查並報告故障。
assertRaises
(exception,callable,* args,** kwds)
測試除法分母為0報異常
class TestMath(unittest.TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_chufa(self):
'''測試乘法程序'''
self.assertEqual(chufa(0,0), 0)
E
======================================================================
ERROR: test_chufa (testmath.TestMath)
測試乘法程序
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\PycharmProjects\unitest\testmath.py", line 87, in test_chufa
self.assertEqual(chufa(0,0), 0)
File "D:\PycharmProjects\unitest\testmath.py", line 74, in chufa
return a/b
ZeroDivisionError: division by zero
----------------------------------------------------------------------
Ran 1 test in 0.001s
加入assertraise斷言后不會報錯
with self.assertRaises(ZeroDivisionError): self.assertEqual(resp['data'], self.a / self.b)
assertRaisesRegex(
exception,regex,callable,* args,** kwds )
也是一樣的操作
with self.assertRaisesRegex(ZeroDivisionError, 'ok'):
self.assertEqual(resp['data'], self.a / self.b)
F
======================================================================
FAIL: test_chufa (testmath.TestMath)
測試乘法程序
----------------------------------------------------------------------
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\PycharmProjects\unitest\testmath.py", line 89, in test_chufa
self.assertEqual(chufa(0,0), 0)
AssertionError: "ok" does not match "division by zero"
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
with self.assertRaisesRegex(ZeroDivisionError, 'by'): self.assertEqual(resp['data'], self.a / self.b)
1 0 <unittest.runner.TextTestResult run=1 errors=0 failures=0> . ---------------------------------------------------------------------- Ran 1 test in 0.028s OK
用於執行更具體檢查的方法
assertAlmostEqual(a, b)
舉個例子self.assertAlmostEqual(1.00000002,1.00000001)第八位不報錯,self.assertAlmostEqual(1.0000001,1.0000002)第七位就會報錯,因為默認比的是第七位之前
self.assertAlmostEqual(1.02,1.01,1)不報錯self.assertAlmostEqual(1.02,1.01,2)報錯,因為默認比的是第二位之前
place參數表示第n位前都相等,之后無所謂
assertRegex
(text,regex,msg = None)
測試正則表達式搜索是否匹配(或不匹配)text。
assertCountEqual
(first,second,msg = None)
測試第一個序列是否包含與第二個相同的元素,而不管它們的順序如何。否則,將生成一條錯誤消息,列出序列之間的差異。
下表總結了自動比較使用的特定類型方法的列表
最后,TestCase
提供以下方法和屬性:
fail
(msg = None )
failureException
此類屬性給出了測試方法引發的異常。如果測試框架需要使用專門的異常(可能帶有其他信息),則它必須將該異常子類化,以便與框架“公平競爭”。此屬性的初始值為 AssertionError
。
使用msg或None
錯誤消息無條件地指示測試失敗。
代碼中加入
if resp['status'] == 0: raise self.failureException(ConnectionError)
並修改測試程序使其返回0
F
======================================================================
FAIL: test_chufa (testmath.TestMath)
測試乘法程序
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\PycharmProjects\unitest\testmath.py", line 89, in test_chufa
raise self.failureException(ConnectionError)
AssertionError: <class 'ConnectionError'>
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
測試框架可以使用以下方法來收集有關測試的信息:
countTestCases
()
返回此測試對象表示的測試數量。
print(TestAdd('test_chengfa').countTestCases()) loader = unittest.TestLoader() suite = loader.loadTestsFromTestCase(TestAdd) print(suite.countTestCases()) suite.addTest(TestAdd('test_chengfa')) print(suite.countTestCases())
1
4
5
id
()
返回標識特定測試用例的字符串。這通常是測試方法的全名,包括模塊和類名。
print(TestAdd('test_chengfa').id())
返回testmath.TestAdd.test_chengfa
shortDescription
()
返回測試的描述,或者None
沒有提供描述。此方法的默認實現返回測試方法docstring的第一行(如果有),或None
。
doCleanups
()
在tearDown()
或在setUp()
引發異常之后無條件調用此方法。
如果使setup方法報錯
def setUp(self):
self.file = open('testtext.txt','w+',encoding='utf-8')
self.file.write('測試開始')
self.a = 1/0
self.b = 2/0
def tearDown(self):
print(self.a)
print(self.b)
self.file.write('測試結束')
self.file.close()
...
runner = unittest.TextTestRunner()
suite = unittest.TestSuite()
suite.addTest(TestAdd('test_add1'))
result = runner.run(suite)
出現錯誤,且不會運行tearDown
E ====================================================================== ERROR: test_add1 (testmath.TestAdd) 測試加法程序 ---------------------------------------------------------------------- Traceback (most recent call last): File "D:\PycharmProjects\untitled\testmath.py", line 11, in setUp self.a = 1/0 ZeroDivisionError: division by zero ---------------------------------------------------------------------- Ran 1 test in 0.001s FAILED (errors=1) <unittest.runner.TextTestResult run=1 errors=1 failures=0>
加入doCleanups
()后
def doCleanups(self): self.file.write('測試結束') self.file.close()
就會將"測試結束"寫入文件了