使用unittest框架

Last Updated: 2023-05-21 08:25:11 Sunday

-- TOC --

软件开发过程中,单元测试是非常重要的,Python自带一个unittest测试框架,可以方便地执行关键函数接口的单元测试。

每一个继承自unittest.TestCase的类,都是一个测试集(test suite)!在执行unittest.main()中,所有这些继承类,都能被自动的找出来,并执行其中以test_开始的测试用例。

在这个测试集内,可以通过setUptearDown函数,来设置每一个属于这个测试集的初始化条件和测试后的清理。即,每一个以test_开头的单元测试函数,在被调用之前,都会执行setUp,执行结束后,都会执行tearDown。

测试集的setUpClasstearDownClass函数,属于整个测试集的初始化和清理,它们只会在测试集运行前和运行后,被执行一次。注意:这两个成员函数,需要被定义为classmethod。

class test_sort_c(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        shell('gcc -fPIC -shared sort.c -o sort.so')
        cls.sort = ctypes.CDLL('./sort.so')

    @classmethod
    def tearDownClass(cls):
        os.remove('sort.so')

    def get_sort(self):
        return test_sort_c.sort

    def setUp(self):
        self.a01 = (1,2,3,4,5,6,7,8,9)
        self.ca01 = (ctypes.c_int*9)(*self.a01)
        self.dca01 = ctypes.byref(self.ca01)
        self.a02 = (9,8,7,6,5,4,3,2,1)
        self.ca02 = (ctypes.c_int*9)(*self.a02)
        self.dca02 = ctypes.byref(self.ca02)

    def tearDown(self):
        pass

    def test_bubble(self):
        sort = self.get_sort()
        sort.bubble(self.dca01, 9)
        self.assertEqual(tuple(self.ca01), self.a01)
        sort.bubble(self.dca02, 0)
        self.assertEqual(tuple(self.ca02), self.a02)
        sort.bubble(self.dca02, -1)
        self.assertEqual(tuple(self.ca02), self.a02)
        sort.bubble(self.dca02, 9)
        self.assertEqual(tuple(self.ca02), self.a01)

setUpClass制作sort.so文件,tearDownClass删除这个文件。这两个动作都需要在整个测试集开始之前和执行后进行,而且只做一次。

setUp函数用于给每个测试单元准备数据,tearDown函数什么都不需要做,留空。

当测试文件存在多个测试集(继承自unittest.TestCase的类),unittest框架可以在执行测试的时候,选择只执行某一个测试集:

$ python3 -m unittest test.test_sort_c
$ python3 test.py test_sort_c

上面的命令,只执行test_sort_c这个测试集。(test_sort_c包含在test.py文件中)

unittest框架还可以提供只执行某一个具体的单元测试函数:

$ python3 -m unittest test.test_common_py.shex
$ python3 test.py test_common_py.shex

这条命令只执行test.py文件中的test_common_py测试集中的shex单元。

unittest框架常用命令行参数:

-v, 显示详细信息,用这个参数,你会发现unittest对于每个测试集中的测试用例,是按照字典顺序调用的,如果想要控制单元测试的执行顺序,可以直接修改测试函数的名称,只要保证这些函数前面5个字母是test_即可,比如test_%d_*

-f, --failfast, 当发生错误的,立即停止。

如何控制按顺序执行部分单元测试用例?

比如有一个测试集内有几十个test case,现在只需要将其中的某几个按某种顺序来执行,可以采用自己创建test suite的方法,代码如下:

if __name__ == '__main__':
    suite = unittest.TestSuite()
    suite.addTest(test_common_py('test_shex'))
    suite.addTest(test_common_py('test_sbin'))
    unittest.main(defaultTest='suite')
    #unittest.TextTestRunner(verbosity=2).run(suite)

创建一个suite,然后添加需要的测试用例,测试添加顺序就是测试的执行顺序,然后执行测试。test_common_py是一个测试集(继承自unittest.TestCase)。

控制测试集的执行

下面的示例代码,可以用来控制执行一个测试文件中的部分测试集。也许有一些测试集我们希望通过在命令行直接输入的方式执行,默认不执行,就可以用这个方法:

unittest.main(defaultTest='test_common_py', exit=False)
unittest.main(defaultTest='test_sort_c')

exit=False,表示执行完后不退出(默认退出),代码就会继续后面的测试集。

简易使用

在学习CS401时,学到了一种简单使用unittest.TestCase对象的方法,即直接使用对象的各种assert接口:

def testfunc(a):
    ...

import unittest
tc = unittest.TestCase()
tc.assertEqual(testfunc(10), 23)
tc.assertEqual(testfunc(500), 57918)
tc.assertEqual(testfunc(1000), 233168)

本文链接:https://cs.pynote.net/sf/python/202206091/

-- EOF --

-- MORE --