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

      

  • 相关阅读:
    (Java实现) 洛谷 P1106 删数问题
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1106 删数问题
    目测ZIP的压缩率
  • 原文地址:https://www.cnblogs.com/vipchenwei/p/7799642.html
Copyright © 2011-2022 走看看