unittest是python自带的单元测试框架,也可与selenium、appinum、requests等一起使用,完成web UI、移动端、接口的测试。
可查看官网:https://docs.python.org/zh-cn/3/library/unittest.html#
1、unittest基本框架
1.1、unittest基本要素
- TestFixture:也叫测试脚手架,主要是用来在测试前后,做一些通用的、前置、后置的工作,比如建立session连接、连接数据库、关闭数据库等
TestFixture包括:setUp(),tearDown(),setUpClass(),tearDownClass(),如果没有case则不会执行
其中setUpClass和tearDownClass是类方法,需添加装饰器@classmethod
- TestCase:测试case
- TestSuite:测试套件,主要用来组装测试case
测试套件,是将所有测试case组装成一个套件,最后封装在一个测试套件中,测试套件其实就是TestSuite的实例,该实例会将所有测试case放入列表中,提供给TestRunner运行
- TestRunner:测试运行器,执行的测试结果。
run(test),其中参数test是测试套件suite
2、unittest使用方法
2.1、一般使用流程
import unittest class ConsoleUI(unittest.TestCase): def setUp(self) -> None: pass def tearDown(self) -> None: pass def test_one_case(self): pass def test_two_case(self): pass
2.2、注意事项
- 待测试的类,需继承自unittest.TestCase,比如待测试的类ConsoleUI,需要继承unittest.TestCase,只有继承自unittest.TestCase,才可使用该类提供的方法,比如断言;
- 每一个测试case必须以test开头,其他的模块/类没有要求不需要以test/Test开头,这是因为在unittest模块中是通过prefix为test开头来查找case;
- 需要写unittest自带的断言,如self.assertEqual(),这是因为unittest模块中,对unittest自带的断言进行了case成功、失败、skip的统计;不要自己写assert语句。
3、unittest运行方式
unittest主要有2种运行方式,包括:命令行运行方式,在__main__方法中指定运行方式。
3.1、命令行方式
python -m unittest bak.py 或 python -m unittest bak # bak.py是所测试的模块,在bak.py模块目录下,第1种方式是通过路径方式,第2种方式可以理解为是通过点“.”方式
python -m unittest bak1 bak2 bakN # 可运行多个模块
python -m unittest test_pkg/bak.py # 通过路径方式,直接运行
python -m unittest test_pkg.bak # 通过点"."方式,运行bak.py模块下所有case
python -m unittest test_pkg.bak.ConsoleUI
python -m unittest test_pkg.bak.ConsoleUI.test_one_case
3.2、在__main__方法中指定运行
3.2.1、通过unittest.main()直接执行
if __name__ == '__main__': unittest.main()
3.2.2、通过loader中提供的,找到测试case,组装测试suite方式来执行
if __name__ == '__main__': suite = unittest.defaultTestLoader.loadTestsFromTestCase(ConsoleUI) runner = unittest.TextTestRunner() runner.run(suite)
# 也可组装多个套件
if __name__ == '__main__': suite1 = unittest.defaultTestLoader.loadTestsFromTestCase(ConsoleUI) suite2 = unittest.defaultTestLoader.loadTestsFromTestCase(ConsoleAPI) suite = unittest.TestSuite() suite.addTests([suite1, suite2]) runner = unittest.TextTestRunner() runner.run(suite)
# 通过路径来查找模块
if __name__ == '__main__': # 通过查找路径来查找测试case start_file = os.path.dirname(__file__) discover = unittest.defaultTestLoader.discover(start_dir=start_file, pattern="bak.py") runner = unittest.TextTestRunner() runner.run(discover)
3.2.3、addTest方式添加单个case
if __name__ == '__main__': suite = unittest.TestSuite() suite.addTest(ConsoleUI("test_one_case")) suite.addTest(ConsoleAPI("test_one_case")) runner = unittest.TextTestRunner() runner.run(suite)
3.2.4、makesuite方式来组装case,不建议使用
if __name__ == '__main__': suite = unittest.makeSuite(ConsoleUI) runner = unittest.TextTestRunner() runner.run(suite)
4、unittest生成结果
最原始的方式,是展示在控制台上,如下,当然这样并不好看。
if __name__ == '__main__': suite = unittest.defaultTestLoader.loadTestsFromTestCase(ConsoleUI) runner = unittest.TextTestRunner() runner.run(suite)
除了展示在控制台上,也可以写入到文件中。这种方式虽然写入到文件,但是文件的内容即控制台上的内容,看起来也并不直观。
if __name__ == '__main__': suite = unittest.defaultTestLoader.loadTestsFromTestCase(ConsoleUI) file_name = "result.html" with open(file_name, "w") as f: runner = unittest.TextTestRunner(stream=f, descriptions="测试结果") runner.run(suite)
4.1、HTMLRunner
from HTMLTestRunner import HTMLTestRunner // 代码块 if __name__ == '__main__': suite = unittest.defaultTestLoader.loadTestsFromTestCase(ConsoleUI) file_name = "result.html" with open(file_name, "w") as f: runner = HTMLTestRunner.HTMLTestRunner(stream=f, verbosity=2, title="测试结果", description="ConsoleUI测试结果") runner.run(suite)
报告如下图:
4.2、BeatifulReport
from BeautifulReport import BeautifulReport as bf // 代码块 if __name__ == '__main__': suite = unittest.defaultTestLoader.loadTestsFromTestCase(ConsoleUI) file_name = "result.html" with open(file_name, "w") as f: runner = bf(suite) runner.report(description="ConsoleUI测试结果", filename=file_name)
报告如下图: