- unittest是python标准库中的模块
- unittest中的几个重要概念
testcase :测试用例,所有测试用例都要继承unittest.TestCase类testfixture :测试开始的准备工作和测试结束后的清理工作testsuite :测试套件,一系列的测试用例或者测试套件testruuner :用于执行和输出测试结果的组件
textfixture
setUp :测试用例的前置操作,运行时每个测试用例均会执行,如果setUp运行发生异常,测试方法不会运行 tearDown : 只要setUp成功运行无论测试方法是否成功,都会运行tearDown setUpClass :测试类的前置操作,@classmethod修饰,和setUp类似 tearDownClass :和tearDown类似 setUpModule : 测试模块的前置操作 tearDownModule :和tearDown类似
例子1
测试代码
import unittest
class testCase(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
print("setupClass")
def setUp(self) -> None:
print("setUp")
@classmethod
def tearDownClass(cls) -> None:
print("teardownClass")
def tearDown(self) -> None:
print("teardown")
def testCaseTwo(self):
print("testCaseTwo")
self.assertTrue(True)
def testCaseOne(self):
print("testCaseOne")
self.assertTrue(True)
class testTwo(unittest.TestCase):
def testcase2(self):
print("testcase2")
self.assertTrue(True)
def setUpModule():
print("setUpmodule")
def tearDownModule():
print("tearDownmodule")
if __name__=="__main__":
unittest.main()
运行结果
D:\Python\program\practic_unittest>python -m unittest test_case.py -v
setUpmodule
setupClass
testCaseOne (mylib.testCase) ... setUp
testCaseOne
teardown
ok
testCaseTwo (mylib.testCase) ... setUp
testCaseTwo
teardown
ok
teardownClass
testcase2 (mylib.testTwo) ... testcase2
ok
tearDownmodule
----------------------------------------------------------------------
Ran 3 tests in 0.012s
OK
例子2
- 修改setUp,让setUp运行失败,可看到测试用例抛出AssertionError:setUp fail的异常
测试代码
def setUp(self) -> None:
self.fail("setUp fail")
print("setUp")
执行结果
D:\Python\program\practic_unittest>python -m unittest test_case.py -v
setupClass
testCaseOne (test_case.testCase) ... FAIL
testCaseTwo (test_case.testCase) ... FAIL
teardownClass
======================================================================
FAIL: testCaseOne (test_case.testCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\Python\program\practic_unittest\test_case.py", line 8, in setUp
self.fail("setUp fail")
AssertionError: setUp fail
======================================================================
FAIL: testCaseTwo (test_case.testCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\Python\program\practic_unittest\test_case.py", line 8, in setUp
self.fail("setUp fail")
AssertionError: setUp fail
----------------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=2)
testcase
断言
常见的有以下断言,更多的断言详见https://docs.python.org/3.8/library/unittest.html#assert-methods assertEqual(a, b, msg=None) 检查a的值是否等于b的值 assertNotEqual(a, b, msg=None) assertTrue(x, msg=None) 检查bool(x)是否为True assertFalse(x, msg=None) 检查bool(x)是否为False assertIs(a, b, msg=None) 检查a和b是否是同一个对象(存储地址是否一样),是则断言通过 assertIsNot(a, b, msg=None) 检查a和b是否是同一个对象,不是则断言通过 assertIsNone(x, msg=None) 检查x是否是None assertIsNotNone(x, msg=None) 检查x是否不是None assertIn(a, b, msg=None) 检查b是否包含a,是则断言通过 assertNotIn(a, b, msg=None) 检查b是否包含a,否则断言通过 assertIsInstance(a, b, msg=None) 检查a是否是b的实例,是则通过 assertNotIsInstance(a, b, msg=None) 检查a是否是b的实例,不是则通过
跳过测试
- 可对测试方法或者测试类添加装饰器,以实现跳过测试
- 亦可对setup添加跳过测试
- 包含以下装饰器:
@unittest.skip(reason) 被装饰的用例跳过执行 @unittest.skipIf(condition, reason) 只有满足条件了才会跳过,不满足条件则执行用例 @unittest.skipUnless(condition, reason) 满足条件不跳过,执行用例,不满足条件则跳过
例子
import unittest
class testStringMethodone(unittest.TestCase):
@unittest.skipIf(mylib.__version__ < (1, 3),
"not supported in this library version")
def test_upper(self):
self.assertEqual('foo'.upper(), 'FOO')
@unittest.skipUnless(sys.platform.startswith("win"), "requires windows")
def test_isupper(self):
self.assertTrue('FOO'.isupper())
@unittest.skip("decorate skip")
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(), ['hello', 'world'])
if __name__ == "__main__":
unittest.main()
__version__=(1,2)
PS D:\Python\program\practic_unittest> python -m unittest test_unittest.py -v
True
test_isupper (test_unittest.testStringMethodone) ... ok
test_split (test_unittest.testStringMethodone) ... skipped 'decorate skip'
test_upper (test_unittest.testStringMethodone) ... skipped 'not supported this library version'
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK (skipped=2)
预计的失败
@unittest.expectedFailure 标记测试用例失败.如果运行有异常,则运行成功,如果运行通过,则运行失败
例子
import unittest
class testStringMethodone(unittest.TestCase):
......
@unittest.expectedFailure
def test_capitalize(self):
self.assertEqual("test".capitalize(), "Test1")
PS D:\Python\program\practic_unittest> python -m unittest test_unittest.py -v
True
test_capitalize (test_unittest.testStringMethodone) ... expected failure
.....
subtest
subTest( msg=None , **params ) ,msg和params是可选值,当运行失败时会回显这些值- subtest返回一个上下文管理器,其下的代码作为子测试,运行失败时,后续测试还会继续,如果不使用subtest,第一次遇到执行失败时就停止了
- 有运行失败的测试用例才会有提示,如果没有直接显示通过
class testStringMethodone(unittest.TestCase):
def test_notuse_subtest(self):
for i in ['str1', "test",'str3']:
self.assertIn("test",i)
def test_use_subtest(self):
for i in ['str1', "test",'str3']:
with self.subTest(i):
self.assertIn("test",i)
运行结果: 
testsuite& 测试执行
- 方法一:使用unittest.main(),收集模块中的所有测试用例并执行
if __name__=="__main__":
unittest.main()
- 添加test_case.py:测试用例文件
import unittest
class testclassOne(unittest.TestCase):
def testCaseTwo(self):
print("testCaseTwo")
self.assertTrue(True)
def testCaseOne(self):
print("testCaseOne")
assert False
class testclassTwo(unittest.TestCase):
def test1(self):
self.assertTrue(False)
- run_testcase.py:执行文件
import unittest
import test_case
import os
def load_by_testcase():
suite = unittest.TestSuite()
suite.addTest(test_case.testclassOne('testCaseTwo'))
suite.addTest(test_case.testclassTwo('test1'))
return suite
def load_by_calss():
suite = unittest.TestSuite()
loader=unittest.TestLoader()
load_suite=loader.loadTestsFromTestCase(test_case.testclassOne)
suite.addTests(load_suite)
return suite
def load_by_pattern(pattern):
this_dir = os.path.dirname(__file__)
suite = unittest.TestSuite()
loader=unittest.TestLoader()
package_tests = loader.discover(this_dir,pattern=pattern)
suite.addTests(package_tests)
return suite
if __name__ == '__main__':
runner = unittest.TextTestRunner()
test_suite=load_by_pattern("*case.py")
runner.run(test_suite)
- 执行结果
PS D:\Python\program\practic_unittest> python run_testcase.py
testCaseOne
FtestCaseTwo
.F
======================================================================
FAIL: testCaseOne (test_case.testclassOne)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\Python\program\practic_unittest\test_case.py", line 9, in testCaseOne
assert False
AssertionError
======================================================================
FAIL: test1 (test_case.testclassTwo)
----------------------------------------------------------------------
Traceback (most recent call last):
File "D:\Python\program\practic_unittest\test_case.py", line 12, in test1
self.assertTrue(False)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 3 tests in 0.001s
FAILED (failures=2)
输出报告
HTMLTestRunner
- 安装HTMLTestRunner:
pip install HTMLTestRunner-Python3 - 添加和修改如下代码
from HTMLTestRunner import HTMLTestRunner
if __name__ == '__main__':
testsuite = load_by_pattern("*case.py")
report_name = 'result_{}.html'.format(time.strftime("%Y.%m.%d_%H_%M_"))
f=open(report_name,'w',encoding='utf-8')
runner = HTMLTestRunner.HTMLTestRunner(stream=f,title='测试报告',description='详情')
runner.run(testsuite)
- 输出结果

BeautifulReport
- 安装BeautifulReport:
pip install BeautifulReport - 添加和修改如下代码
from BeautifulReport import BeautifulReport
if __name__ == '__main__':
testsuite = load_by_pattern("*case.py")
run = BeautifulReport(testsuite)
report_name ='result_{}.html'.format( time.strftime("%Y.%m.%d_%H_%M_"))
run.report(description='beautifulreport', filename=report_name)
- 输出报告

命令行执行
python -m unittest 执行可找到的所有testcase,等价python -m unittest discover python -m unittest test_module/test_module.TestClass/test_module.TestCalss.test_method 指定运行的模块/类/测试方法 python -m unittest tests/test_something.py 测试模块亦可通过测试文件路径指定 -v :输出详细结果 -f :第一个错误或者失败时就停止测试 -k :只运行匹配的testcase,eg:-k name,只匹配模式或测试方法和类,并且大小写敏感
探索性测试
python -m unittest discover :只会匹配test*.py文件 参数: -v, --verbose :更详细地输出结果。
-s, --start-directory directory :开始进行搜索的目录(默认值为当前目录 . )。
-p, --pattern pattern :用于匹配测试文件的模式(默认为 test*.py )。
-t, --top-level-directory directory :指定项目的最上层目录(通常为开始时所在目录)
学习文档:https://docs.python.org/3.8/library/unittest.html#
|