Python单元测试unittest

Python 中有一个自带的单元测试框架是 unittest 模块,用它来做单元测试,它里面封装好了一些校验返回的结果方法和一些用例执行前的初始化操作。

在说 unittest 之前,先说几个概念:

TestCase 也就是测试用例

TestSuite 多个测试用例集合在一起,就是 TestSuite

TestLoader 是用来加载 TestCase 到 TestSuite 中的

TestRunner 是来执行测试用例的, 测试的结果会保存到 TestResult 实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息

下面写一个简单的单元测试用例

import unittest

class MyTest(unittest.TestCase): # 继承 unittest.TestCase
def tearDown(self):
# 每个测试用例执行之后做操作
print('111')

</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> setUp(self):
    </span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 每个测试用例执行之前做操作</span>
    <span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">22222</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

@classmethod
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> tearDownClass(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 必须使用 @ classmethod装饰器, 所有test运行完后运行一次</span>
     <span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">4444444</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
@classmethod
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> setUpClass(self):
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 必须使用@classmethod 装饰器,所有test运行前运行一次</span>
    <span style="color: rgba(0, 0, 255, 1)">print</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">33333</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)

</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_a_run(self):
    self.assertEqual(</span>1, 1)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 测试用例</span>
    
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_b_run(self):
    self.assertEqual(</span>2, 2)  <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 测试用例</span>

if name == 'main':
unittest.main()
#运行所有的测试用例

下面是一些常用的断言,也就是校验结果

        assertEqual(a, b)     a == b      
        assertNotEqual(a, b)     a != b      
        assertTrue(x)     bool(x) is True      
        assertFalse(x)     bool(x) is False      
        assertIsNone(x)     x is None     
        assertIsNotNone(x)     x is not None   
        assertIn(a, b)     a in b    
        assertNotIn(a, b)     a not in b

那如何生成一个测试报告呢,需要加入另外一个模块了,HTMLTestRunner,这个模块需要自己安装,使用执行测试用例就会生成一个 html 的测试报告,里面会有每个测试用例的执行结果,代码如下:

        import HTMLTestRunner        
        import unittest
        class MyTest(unittest.TestCase):#继承 unittest.TestCase
            def tearDown(self):
                #每个测试用例执行之后做操作
                print('111')
            def setUp(self):
                #每个测试用例执行之前做操作
                print(22222)
            def test_run(self):
                # self.assertEqual(1,1)
                self.assertIs(1,1)
                #测试用例
            def test_run2(self):
                # self.assertEqual(1,1)
                self.assertIs(1,1)
                #测试用例
            def test_run3(self):
                # self.assertEqual(1,1)
                self.assertIs(1,1)
                #测试用例
            def test_run1(self):
                # self.assertEqual(1,1)
                self.assertIs(1,1)
                #测试用例
        if __name__ == '__main__':
            test_suite = unittest.TestSuite()#创建一个测试集合
            test_suite.addTest(MyTest('test_run1'))#测试套件中添加测试用例
            #test_suite.addTest(unittest.makeSuite(MyTest))# 使用 makeSuite 方法添加所有的测试方法
            fp = open('res.html','wb')#打开一个保存结果的 html 文件
            runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='api 测试报告',description='测试情况')
            #生成执行用例的对象
            runner.run(test_suite)
            #执行测试套件

如果我们有很多个模块,每个模块下面都写了很多 python 文件,每个 python 文件里面都有测试用例,那怎么把这个目录下的用例都执行了呢,就要先找到这个目录下的所有 python 文件,然后找到里面的测试用例,逐个执行,代码如下:

        import unittest,HTMLTestRunner
        suite = unittest.TestSuite()#创建测试套件
        all_cases = unittest.defaultTestLoader.discover('.','test_*.py')
        #找到某个目录下所有的以 test 开头的 Python 文件里面的测试用例
        for case in all_cases:
            suite.addTests(case)#把所有的测试用例添加进来
        fp = open('res.html','wb')
        runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title='all_tests',description='所有测试情况')runner.run(suite)
        #运行测试

我们在后续进行持续集成的时候,要让代码自动运行,就会用到 Jenkins 了,但是上面产生的测试报告都是 html 格式的,Jenkins 不认识,就在 Jenkins 里面显示不出来。那咱们就要产生一些 Jenkins 认识的测试报告,Jenkins 认识 xml 格式的报告,那咱们就产生 xml 格式的呗,就需要用一个新的模块,xmlrunner,安装直接 pip install xmlrunner 即可,代码如下:

import unittest
import xmlrunner
#导入这个模块
class My(unittest.TestCase):
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test1(self,a,b,c):
    self.assertEqual(a</span>+<span style="color: rgba(0, 0, 0, 1)">b,c)

if name=='main':
test_suite
= unittest.TestSuite()
test_suite.addTest(unittest.makeSuite(My))
runner
= xmlrunner.XMLTestRunner(output='report')#指定报告放的目录
runner.run(test_suite)

然后咱们运行,可以看到在 report 目录下已经产生了 xml 格式的报告了,而且还自动把日期加上了