• 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() 方法即可

  • 相关阅读:
    getContentResolver()内容解析者查询联系人、插入联系人
    ContentProvider备份短信,以xml文件存储
    ContentProvider详解
    bindService初步了解
    Service之来电监听(失败的案例)
    Android帧动画
    AlertDialog之常见对话框(单选对话框、多选对话框、进度条对话框)
    BroadcastReceiver之(手动代码注册广播)屏幕锁屏、解锁监听、开机自启
    BroadcastReceiver之有序广播
    [FJOI2015]火星商店问题
  • 原文地址:https://www.cnblogs.com/dbf-/p/11673094.html
Copyright © 2020-2023  润新知