码迷,mamicode.com
首页 > 编程语言 > 详细

Python单元测试之unittest

时间:2019-03-25 14:42:28      阅读:195      评论:0      收藏:0      [点我收藏+]

标签:ret   冗余代码   mmu   htm   blog   second   跳过   验证   from   

摘抄自:

Python单元测试——深入理解unittest

Python3 — unittest框架的使用

 

一、基础概念

unittest官方文档:https://docs.python.org/3.5/library/unittest.html

技术图片

  • TestCase:一个TestCase的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。
  • TestSuite:而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。
  • TestLoader:是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。
  • TextTestRunner:是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。
  • TextTestResult:测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息

那么整个流程就是:首先是要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中

 

二、测试案例分析

1、示例1

# 这是unittest文档上的例子
import random
import unittest
 
class TestSequenceFunctions(unittest.TestCase):
 
    def setUp(self):
        self.seq = range(10)
 
    def test_shuffle(self):
        # make sure the shuffled sequence does not lose any elements
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, range(10))
 
        # should raise an exception for an immutable sequence
        self.assertRaises(TypeError, random.shuffle, (1,2,3))
 
    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)
 
    def test_sample(self):
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)
 
if __name__ == __main__:
    unittest.main()

TestSequenceFunctions继承自unittest.TestCase,重写了setUp()方法,并且定义了三个以‘test‘开头的方法,那这个TestSequenceFunctions类到底是个什么呢?它是一个测试用例,还是三个测试用例?说是三个测试用例的话,它本身继承自TestCase,说是一个测试用例的话,里面又有三个test_*()方法,明显是三个测试用例。其实,我们只要看一些TestLoader是如何加载测试用例的,就一清二楚了,在loader.TestLoader类中有一个loadTestsFromTestCase()方法:

    def loadTestsFromTestCase(self, testCaseClass):
        """Return a suite of all tests cases contained in testCaseClass"""
        if issubclass(testCaseClass, suite.TestSuite):
            raise TypeError("Test cases should not be derived from TestSuite."                                 " Maybe you meant to derive from TestCase?")
        testCaseNames = self.getTestCaseNames(testCaseClass)
        if not testCaseNames and hasattr(testCaseClass, runTest):
            testCaseNames = [runTest]
        loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
        return loaded_suite

getTestCaseNames()是从TestCase这个类中找所有以“test”开头的方法,然后注意第9行,在构造TestSuite对象时,其参数使用了一个map方法,即对testCaseNames中的每一个元素,使用testCaseClass为其构造对象,其结果是一个TestCase的对象集合,可以用下面的代码来分步说明:

testcases = []
for name in testCaeNames:
    testcases.append(TestCase(name))
loaded_suite = self.suiteClass(tuple(testcases))

可见,对每一个以test开头的方法,都为其构建了一个TestCase对象,值得注意的是,如果没有定义test开头的方法,而是将测试代码写到了一个名为runTest的方法中,那么会为该runTest方法构建TestCase对象,如果定义了test开头的方法,就会忽略runTest方法。

 

也就是说:
每一个以test开头的方法,都会为其构建TestCase对象,也就是说TestSequenceFunctions类中其实定义了三个TestCase,之所以写成这样,是为了方便,因为这几个测试用例的fixture是相同的,如果每一个测试用例单独写成一个TestCase的话,会有很多的冗余代码。

2、示例2

前置条件(setUp)、后置条件(tearDown)和Test Suite的使用

import unittest


class TestCase_01(unittest.TestCase):  # 继承unittest.TestCase

    @classmethod
    def setUpClass(cls):
        print(这是所有case的前置条件01)

    @classmethod
    def tearDownClass(cls):
        print(这是所有case的后置条件01)

    def setUp(self):
        print(这是每条case的前置条件01)

    def tearDown(self):
        print(这是每条case的后置条件01)

    def testThird_01(self):  # 测试用例的命名必须以test开头,否则不予执行
        print(01: 第三条case)

    def testFirst_01(self):
        print(01: 第一条case)

    @unittest.skip(不执行这条case)  # 跳过这条case
    def testSecond_01(self):
        print(01: 第二条case)

    def testFourth_01(self):
        print(01: 第四条case)


if __name__ == __main__:
    # unittest.main() # 使用main()直接运行时,将按case的名称顺序执行
    suite = unittest.TestSuite()
    suite.addTest(TestCase_01(testThird_01))  # 将需要执行的case添加到Test Suite中,没有添加的不会被执行
    suite.addTest(TestCase_01(testSecond_01))
    suite.addTest(TestCase_01(testFirst_01))
    unittest.TextTestRunner().run(suite)  # 将根据case添加的先后顺序执行

 

结果

这是所有case的前置条件01
OK (skipped=1)
这是所有case的后置条件01这是每条case的前置条件01
01: 第一条case
这是每条case的后置条件01


Ran 4 tests in 0.016s
这是每条case的前置条件01
01: 第四条case
这是每条case的后置条件01

Skipped: 不执行这条case
这是每条case的前置条件01
01: 第三条case
这是每条case的后置条件01

 

Python单元测试之unittest

标签:ret   冗余代码   mmu   htm   blog   second   跳过   验证   from   

原文地址:https://www.cnblogs.com/Zzbj/p/10593415.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!