zoukankan      html  css  js  c++  java
  • python单元测试

    一、几个重要概念

    test fixture
      test fixture表示执行一个或多个测试所需的准备工作,以及任何关联清理操作。这可能涉及例如创建临时或代理数据库,目录或启动服务器进程。
    test case
      test case是单元测试的最小单位。它检查对特定输入集的特定响应。unittest 提供了一个基类, TestCase可用于创建新的测试用例。
    test suite
      test suite是test cases,test suites或者两者的集合。它用于聚合应该一起执行的测试。
    test runner
      test runner 是一个协调测试执行并向用户提供结果的组件。执行者可以使用图形界面,文本界面,或返回特殊值来指示执行测试的结果。

    二、unittest测试流程

        

      

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

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

      现在已经涉及到了test case, test suite, test runner这三个概念了,还有test fixture没有提到,那什么是test fixture呢??在TestCase的docstring中有这样一段话:

      Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively.

      可见,对一个测试用例环境的搭建和销毁,是一个fixture,通过覆盖TestCase的setUp()和tearDown()方法来实现。这个有什么用呢?比如说在这个测试用例中需要访问数据库,那么可以在setUp()中建立数据库连接以及进行一些初始化,在tearDown()中清除在数据库中产生的数据,然后关闭连接。注意tearDown的过程很重要,要为以后的TestCase留下一个干净的环境。关于fixture,还有一个专门的库函数叫做fixtures,功能更加强大,以后会介绍到。

      至此,概念和流程基本清楚了,下面通过简单的例子再来实践一下,就拿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的话,会有很多的冗余代码。

      明白了这些,文档就可以很轻松的看懂了,至于怎么运行测试用例,以及其他的内容,直接看文档吧。

    本文转自:http://blog.csdn.net/hackerain/article/details/24095117

    几种常见测试框架:http://www.cnblogs.com/miniren/p/5175770.html

      

  • 相关阅读:
    vue axios创建实例
    vue axios全局配置
    vue axios并发请求
    vue axios HTTP 库
    vuex actions异步操作
    vuex getters
    Go并发控制--Channel篇
    UVA10228 A Star not a Tree?
    P1395 会议
    P1337 [JSOI2004]平衡点 / 吊打XXX
  • 原文地址:https://www.cnblogs.com/vipchenwei/p/7799642.html
Copyright © 2011-2022 走看看