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)
此参数在***已经详细介绍,不重复介绍
debug
()
运行测试而不收集结果。这样可以将测试引发的异常传播到调用方,并可以用于支持在调试器下运行测试。
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报异常
def test_chufa(self): '''测试除法程序''' self.b = 0 headers = { 'Content-Type': "application/json", } reqdata = {'a':self.a,'b':self.b} resp = requests.request(method='POST', url='http://127.0.0.1:8000/testapi/chengfa/', verify=False, headers=headers, json=reqdata) resp = json.loads(resp.text) self.assertEqual(resp['status'],1) self.assertEqual(resp['message'], '请求成功') self.assertEqual(resp['data'], self.a / self.b)
1 0 <unittest.runner.TextTestResult run=1 errors=1 failures=0> E ====================================================================== ERROR: test_chufa (testmath.TestAdd) 测试除法程序 ---------------------------------------------------------------------- Traceback (most recent call last): File "D:\PycharmProjects\untitled\testmath.py", line 67, in test_chufa self.assertEqual(resp['data'], self.a / self.b) ZeroDivisionError: division by zero ---------------------------------------------------------------------- Ran 1 test in 0.029s FAILED (errors=1)
加入assertraise断言后不会报错
with self.assertRaises(ZeroDivisionError): self.assertEqual(resp['data'], self.a / self.b)
1 0 <unittest.runner.TextTestResult run=1 errors=0 failures=0> . ---------------------------------------------------------------------- Ran 1 test in 0.030s OK
assertRaisesRegex(
exception,regex,callable,* args,** kwds )
也是一样的操作
with self.assertRaisesRegex(ZeroDivisionError, 'ok'):
self.assertEqual(resp['data'], self.a / self.b)
F ====================================================================== FAIL: test_chufa (testmath.TestAdd) 测试除法程序 ---------------------------------------------------------------------- ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "D:\PycharmProjects\untitled\testmath.py", line 68, in test_chufa self.assertEqual(resp['data'], self.a / self.b) AssertionError: "ok" does not match "division by zero" ---------------------------------------------------------------------- Ran 1 test in 0.030s FAILED (failures=1) 1 0 <unittest.runner.TextTestResult run=1 errors=0 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)
并修改测试程序使其返回status:0
1 2 <unittest.runner.TextTestResult run=1 errors=0 failures=1> F ====================================================================== FAIL: test_add1 (testmath.TestAdd) 测试加法程序 ---------------------------------------------------------------------- Traceback (most recent call last): File "D:\PycharmProjects\untitled\testmath.py", line 26, in test_add1 raise self.failureException(ConnectionError) AssertionError: <class 'ConnectionError'> ---------------------------------------------------------------------- Ran 1 test in 0.035s 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()
就会将"测试结束"写入文件了