python3 unittest

2018-12-06  本文已影响0人  halfempty

1 介绍

unittest借鉴了JUnit的思想,支持测试代码的初始化(setup)和回收(teardown),测试集,以及测试报告框架与测试用例的独立性

The unittest unit testing framework was originally inspired by JUnit and has a similar flavor as major unit testing frameworks in other languages. It supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework.

几个重要的概念

2 TestCase

定义class,继承unittest.TestCase

测试方法必须以test开头,如test_case1, test_case2...

__init__, setUp, tearDown每个方法均会调用一次

另外支持class级别的setUpClass, tearDownClass

实现参数化,可以借助subTest()

class MyTestCase(unittest.TestCase):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print('init ')

    @classmethod
    def setUpClass(cls):
        print('class setup')

    @classmethod
    def tearDownClass(cls):
        print('class teardown')

    def setUp(self):
        print('setup')

    def tearDown(self):
        print('teardown')

    def test_case1(self):
        print('test case1')
        self.assertTrue(True)

    def test_case2(self):
        print('test case2')
        self.assertFalse(False)

    @unittest.expectedFailure
    def test_fail(self):
        self.assertEqual(1, 0, 'broken')

    def test_case4(self):
        for i in range(6):
            with self.subTest(v = i):
                self.assertTrue(i % 2 == 0)

if __name__ == "__main__":
    unittest.main()

3 TestSuit

TestSuit可以嵌套,因此可以实现分组功能

if __name__ == "__main__":
    suite = unittest.TestSuite();
    suite.addTest(MyTestCase('test_case1'))
    suite.addTest(MyTestCase('test_case2'))

    runner = unittest.TextTestRunner()
    runner.run(suite)

4 程序入口

执行下面的语句将测试当前的TestCase,跟踪代码发现就是实例化TestProgram

if __name__ == '__main__':
    unittest.main()

重点看TestProgram.__init__方法,

self.parseArgs(argv)   //初始化参数,加载用例下的测试方法
self.runTests()    //执行测试用例

4-1 加载测试方法

具体如何加载测试方法的,请继续往下看

执行createTests方法,可见方法由加载器从module内读取

self.test = self.testLoader.loadTestsFromModule(self.module)

先看loadTestsFromModule

//使用dir方法查看module内的所有属性、方法、类等
//如果是TestCase的子类,则从中提取测试方法
for name in dir(module):
    obj = getattr(module, name)
    if isinstance(obj, type) and issubclass(obj, case.TestCase):
        tests.append(self.loadTestsFromTestCase(obj))

再来看loadTestsFromTestCase是如何从TestCase中读取method的

  1. 同样使用dir查看TestCase与的属性和方法
  2. 通过isTestMethod方法过滤,是否可调用(callable,即方法)并且是否以test开头(testMethodPrefix默认=test,所以要求测试方法必须以test开头,否则无法识别)
  3. 按字典顺序排序
def getTestCaseNames(self, testCaseClass):
    def isTestMethod(attrname, testCaseClass=testCaseClass,
                     prefix=self.testMethodPrefix):
        return attrname.startswith(prefix) and \
            callable(getattr(testCaseClass, attrname))
    testFnNames = list(filter(isTestMethod, dir(testCaseClass)))
    if self.sortTestMethodsUsing:
        testFnNames.sort(key=functools.cmp_to_key(self.sortTestMethodsUsing))
    return testFnNames

最后调用TestCase(methodName)实例化,所以有多少方法就会实例化多个个case对象,即执行__init__

4-2 执行流程

5 命令行执行

取自官网,可以传入module,TestCase类,甚至TestCase下的具体方法

python -m unittest test_module1 test_module2
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method

如果未传入测试对象参数,将启动自动加载TestLoader.discover()

上一篇 下一篇

猜你喜欢

热点阅读