unittest模块
1,基本使用
先准备好要测试的文件,如project.py
def add(a, b): return a + b def divide(a, b): return a / b def even(a): if a % 2 == 0: return True else: return False
再新建一个test.py文件,里面的测试方法必须以test开头,不然识别不了
import unittest from project import add, divide, even class Test_Project(unittest.TestCase): def setUp(self) -> None: """可用来准备测试前的环境""" print("每个测试方法执行前触发") def tearDown(self) -> None: """可用来还原测试后的环境""" print("每个测试方法执行后触发") def test_add(self): print("add") self.assertEqual(4, add(1, 3)) self.assertNotEqual(4, add(1, 2)) def test_divide(self): print("divide") self.assertEqual(3, divide(9, 3)) self.assertNotEqual(3, divide(4, 2)) def test_even(self): print("even") self.assertTrue(even(4)) self.assertTrue(even(9)) self.assertFalse(even(7)) if __name__ == '__main__': # 执行整个测试单元 unittest.main()
执行结果如下:..F表示测试的三个方法里面有一个失败,需要测试的方法不是安装写的先后顺序来执行的,是按照方法名的数字字母的排序来执行的。
每个测试方法执行前触发 add 每个测试方法执行后触发 每个测试方法执行前触发 devide 每个测试方法执行后触发 每个测试方法执行前触发 is_prime 每个测试方法执行后触发 ..F ====================================================================== FAIL: test_even (__main__.Test_Project) ---------------------------------------------------------------------- Traceback (most recent call last): File "D:/PycharmProjects/PM/test01/test.py", line 26, in test_even self.assertTrue(even(9)) AssertionError: False is not true ---------------------------------------------------------------------- Ran 3 tests in 0.000s FAILED (failures=1) Process finished with exit code 1
2,使用TestSuite来控制测试的执行顺序
将main方法替换成如下
if __name__ == '__main__': tests = [Test_Project("test_divide"), Test_Project("test_even"), Test_Project("test_add")] suite = unittest.TestSuite() suite.addTests(tests) runner = unittest.TextTestRunner() runner.run(suite)
3,如果只希望在所有测试方法执行前只准备一次环境或者只还原一次环境
class Test_Project(unittest.TestCase): @classmethod def setUpClass(cls) -> None: """可用来准备测试前的环境""" print("第一个测试方法执行前触发") @classmethod def tearDownClass(cls) -> None: """可用来还原测试后的环境""" print("最后一个测试方法执行后触发")
4,使用skip装饰器跳过某个case
被跳过的case执行结果会显示为S
@unittest.skipUnless(sys.platform.startswith("Linux"), "required Linux") def test_divide(self): print("divide") self.assertEqual(3, divide(9, 3)) self.assertNotEqual(3, divide(4, 2))
一共有三种skip装饰器和一种预期失败装饰器,就是不管执行结果是什么, 直接将case设置为失败
unittest.skip(reason):无条件跳过测试的装饰器,说明跳过的原因 unittest.skipIf(condition, reason):如果条件为真,跳过测试的装饰器,reason说明跳过的理由 unittest.skipUnless(condition, reason):跳过测试的装饰器,除非条件为真,reason说明跳过的理由
unittest.expectedFailure():测试标记为失败。不管执行结果是否失败,统一标记失败。
5,将执行结果输出
输出的结果的信息用TextTestRunner方法的参数表示
if __name__ == '__main__': tests = [Test_Project("test_divide"), Test_Project("test_even"), Test_Project("test_add")] suite = unittest.TestSuite() suite.addTests(tests) with open(r"report", "a") as f: # verbosity为0表示不输出用力的执行结果,为1表示一般输出,为2表示仔细输出,默认为1 runner = unittest.TextTestRunner(stream=f, verbosity=2) runner.run(suite)
输出为HTML格式
将HTMLTestRunner.py文件下载放到当前目录下: http://tungwaiyip.info/software/HTMLTestRunner.html
from HTMLTestRunner import HTMLTestRunner with open('report.html', 'a') as f: runner = HTMLTestRunner( stream=f, title='Test Report', verbosity=2 ) runner.run(suite)
6,自动加载测试用例
另起一个文件,跟test.py和project.py在同一个目录下
loader = unittest.TestLoader() suite = unittest.TestSuite()
# 加载一个类 loader.loadTestsFromTestCase(test.TestRpoject) suite.addTests(loader.loadTestsFromModule(test)) with open(r"report", "a") as f: runner = unittest.TextTestRunner(stream=f, verbosity=2) runner.run(suite)
discover方法: discover(start_dir, pattern='test*.py', top_level_dir=None)
# discover方法,自动查找test_dir目录下所有测试用例 test_dir = './test_case' discover = unittest.defaultTestLoader.discover(test_dir,pattern='test*.py') if __name__ == '__main__': runner = unittest.TextTestRunner() runner.run(discover)