zoukankan      html  css  js  c++  java
  • Python unittest

    Python unittest

    unittest 是Python 自带的单元测试框架,用它来做单元测试,它里面封装好了一些校验返回的结果方法和一些用例运行前的初始化操作。
    官方文档:https://docs.python.org/3/library/unittest.html#module-unittest

    简介

    unittest 中有一些类:

    TestCase 测试用例
    TestSuite 多个测试用例集合在一起,就是TestSuite
    TestLoader 用来加载 TestCase 到 TestSuite 中的
    TestRunner 是来运行测试用例的, 测试的结果会保存到 TestResult 实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息

    使用

    unittest 要求单元测试类必须继承 unittest.TestCase,该类中的测试方法需要满足如下要求:

    • 没有返回值
    • 不应该有任何参数
    • 应以test 开头

    示例:

    import unittest
    
    
    class TestFunc(unittest.TestCase):
        def test_1(self):
            self.assertEqual(func1(1, 1), 2)
    
        def test_2(self):
            self.assertEqual(func1(1, 2), 3)
    
    
    def func1(a, b):
        return a + b
    
    
    if __name__ == '__main__':
        unittest.main()
    
    

    返回结果:

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK
    

    断言方法

    常用的方法:

    断言方法 检查条件
    assertEqual(a, b) a == b
    assertNotEqual(a, b) a != b
    assertTrue(x) bool(x) is True
    assertFalse(x) bool(x) is False
    assertIs(a, b) a is b
    assertIsNot(a, b) a is not b
    assertIsNone(x) x is None
    assertIsNotNone(x) x is not None
    assertIn(a, b) a in b
    assertNotIn(a, b) a not in b
    assertlsInstance(a, b) isinstance(a, b)
    assertNotIsInstance(a, b) not isinstance(a, b)

    包含检查 exceptions, warnings, and log messages 的方法:

    断言方法 检查条件
    assertRaises(exc, fun, *args, **kwds) fun(*args, **kwds) raises exc 异常
    assertRaisesRegex(exc, r, fun, *args, **kwds) fun(*args, **kwds) raises exc 异常,且异常信息匹配正则表达式 r
    assertWarns(warn, fun, *args, **kwds) fun(*args, **kwds) raises warn 警告
    assertWarnsRegex(warn, r, fun, *args, **kwds) fun(*args, **kwds) raises warn 警告,且异常信息匹配正则表达式 r
    assertLogs(logger, level) with 语句块使用日志器 (logger) 生成 level 级别的日志

    包含特定检查的方法:

    断言方法 检查条件
    assertAlmostEqual(a, b) round(a-b, 7) == 0
    assertNotAlmostEqual(a, b) round(a-b, 7) != 0
    assertGreater(a, b) a > b
    assertGreaterEqual(a, b) a >= b
    assertLess(a, b) a < b
    assertLessEqual(a, b) a <= b
    assertRegex(s, r) r.search(s)
    assertNotRegex(s, r) not r.search(s)
    assertCountEqual(a, b) a、b 包含的元素及其数量相同,无视顺序 等效于`assertEqual(Counter(list(first)), Counter(list(second)))`

    返回结果

    第一行表示每个测试用例的运行结果:

    从第一个开始表示相应顺序的测试用例运行结果
    .: 测试通过
    F: FAILURE 测试失败
    E: ERROR 测试出错
    S: Skip 跳过该测试

    之后是错误信息 (如果有的话):
    示例:

    ======================================================================
    ERROR: test_1 (__main__.TestFunc)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "test.py", line 30, in func1
        raise IndexError
    IndexError
    
    
    ======================================================================
    FAIL: test_2 (__main__.TestFunc)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "text.py", line 27, in test_2
        self.assertEqual(func1(1, 2), 4)
    AssertionError: 3 != 4
    
    

    如果是测试出错,会将错误显示出来
    如果是测试失败,会将失败原因以及函数运行的实际结果和期望结果的差异显示出来

    最后是所有测试用例的运行结果:

    示例:

    ----------------------------------------------------------------------
    Ran 3 tests in 0.000s
    
    FAILED (failures=1, errors=1)
    
    ----------------------------------------------------------------------
    Ran 3 tests in 0.000s
    
    OK
    

    会显示本次测试一共运行了几个测试用例,以及运行时间
    最后是运行的结果
    OK: 所有测试用例均通过
    FAILED: 没有全部通过 (以及失败数量和错误数量)

    运行顺序

    在 TestCase 中有一些特殊的方法:
    setUp: 每个测试用例之前运行
    tearDown: 每个测试用例之后运行
    setUpClass: 所有测试用例之前 (setUp) 运行
    tearDownClass: 所有测试用例之后 (tearDown) 运行

    运行顺序示例:

    import unittest
    
    
    class TestFunc(unittest.TestCase):
        def tearDown(self) -> None:
            print('from tearDown')
    
        def setUp(self) -> None:
            print('from setUp')
    
        @classmethod
        def tearDownClass(cls) -> None:
            print('from tearDownClass')
    
        @classmethod
        def setUpClass(cls) -> None:
            print('from setUpClass')
    
        def test_1(self):
            self.assertEqual(func1(1, 1), 2)
    
        def test_2(self):
            self.assertEqual(func1(1, 2), 3)
    
    
    def func1(a, b):
        return a + b
    
    
    if __name__ == '__main__':
        unittest.main()
    
    

    返回结果

    from setUpClass
    ..
    from setUp
    ----------------------------------------------------------------------
    from tearDown
    Ran 2 tests in 0.000s
    from setUp
    
    from tearDown
    from tearDownClass
    OK
    
    

    运行多个测试用例

    使用 unittest.main() 会直接运行所有的测试用例,如果希望只运行一些特定的测试用例,就需要用到 TestSuite
    TestSuite 是许多测试用例的集合,通过 addTest() 方法将测试用例添加到 TestSuite
    之后实例化一个 TextTestRunner(TestRunner) 类,最后调用 run() 就可以运行测试用例了

    示例:

    import unittest
    from typing import Any
    # import HTMLTestRunner
    
    
    class MyTestFunc1(unittest.TestCase):
        def test_1(self):
        	print('from Func1 test_1')
            self.assertEqual(func1(1, 1), 2)
    
        def test_2(self):
        	print('from Func1 test_2')
            self.assertNotEqual(func1(1, 2), 4)
    
    
    class MyTestFunc2(unittest.TestCase):
        def test_1(self):
        	print('from Func2 test_1')
            self.assertTrue(func1(1, 2))
    
    
    def func1(a, b):
        return a + b
    
    
    if __name__ == '__main__':
        test_suite = unittest.TestSuite()
        test_suite.addTest(unittest.makeSuite(MyTestFunc2))
        test_suite.addTest(MyTestFunc1('test_1'))
        runner = unittest.TextTestRunner()
        runner.run(test_suite)
    
    

    返回结果:

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK
    from Func2 test_1
    from Func1 test_1
    
    

    可以看出只有 MyTestFunc1 中的 test_1 和 MyTestFunc2 中的 test_1 运行了
    并且运行顺序取决于添加到 TestSuite 中的顺序

    获取报告

    通过 TextTestRunner 类可以将测试结果储存到文件中,而不是直接打印出来,只需要实例化时传入相关参数即可

    f = open('report.txt', 'w')
    runner = unittest.TextTestRunner(stream=f)
    

    还有一些其他的参数,可以在 TextTestRunner 类源码中看到

    其他模块

    通过其他模块可以获取其他格式的测试结果
    这些模块需要单独安装 HTMLTestRunnerxmlrunner
    使用方法相似,实例化时传入必要的参数,之后调用 run() 方法即可

  • 相关阅读:
    27. Remove Element
    列表变成字典
    1. Two Sum
    CVPR2019:What and How Well You Performed? A Multitask Learning Approach to Action Quality Assessment
    959. Regions Cut By Slashes
    118. Pascal's Triangle
    loj3117 IOI2017 接线 wiring 题解
    题解 NOI2019 序列
    题解 省选联考2020 组合数问题
    题解 Educational Codeforces Round 90 (Rated for Div. 2) (CF1373)
  • 原文地址:https://www.cnblogs.com/dbf-/p/11673094.html
Copyright © 2011-2022 走看看