Python中的测试工具

系统 1475 0

  当我们在写程序的时候,我们需要通过测试来验证程序是否出错或者存在问题,但是,编写大量的测试来确保程序的每个细节都没问题会显得很繁琐。在Python中,我们可以借助一些标准模块来帮助我们自动完成测试过程,比如:

  • unittest: 一个通用的测试框架;
  • doctest: 一个更简单的模块,是为检查文档而设计的,但也非常适合用来编写单元测试。

  下面,笔者将会简单介绍这两个模块在测试中的应用。

doctest

  doctest模块会搜索那些看起来像是python交互式会话中的代码片段,然后尝试执行并验证结果。下面我们以doctest.testmod为例,函数doctest.testmod会读取模块中的所有文档字符串,查找看起来像是从交互式解释器中摘取的示例,再检查这些示例是否反映了实际情况。
  我们先创建示例代码文件test_string_lower.py,完整代码如下:

            
              
                # -*- coding: utf-8 -*-
              
              
                def
              
              
                string_lower
              
              
                (
              
              string
              
                )
              
              
                :
              
              
                '''
    返回一个字符串的小写
    :param string: type: str
    :return: the lower of input string
    >>> string_lower('AbC')
    'abc'
    >>> string_lower('ABC')
    'abc'
    >>> string_lower('abc')
    'abc'
    '''
              
              
                return
              
               string
              
                .
              
              lower
              
                (
              
              
                )
              
              
                if
              
               __name__ 
              
                ==
              
              
                '__main__'
              
              
                :
              
              
                import
              
               doctest
              
                ,
              
               test_string_lower
    doctest
              
                .
              
              testmod
              
                (
              
              test_string_lower
              
                )
              
            
          

首先先对程序进行说明,函数string_lower用于返回输入字符串的小写,函数中的注释中,一共包含了3个测试实例,期望尽可能地包含各种测试情况,接着在主函数中导入doctest, test_string_lower,再运行doctest中的testmod函数即可进行测试。
  接着,我们开始测试。首先,在命令行中输入 python test_string_lower.py ,运行后会发现什么都没有输出,但这其实是件好事,它表明程序中的所有测试都通过了!那么,如果我们想要获得更多的输出呢?可在运行脚本的时候增加参数 -v ,这时候命令变成 python test_string_lower.py -v ,输出的结果如下:

            
              Trying:
    string_lower
              
                (
              
              
                'AbC'
              
              
                )
              
              
Expecting:
    
              
                'abc'
              
              
ok
Trying:
    string_lower
              
                (
              
              
                'ABC'
              
              
                )
              
              
Expecting:
    
              
                'abc'
              
              
ok
Trying:
    string_lower
              
                (
              
              
                'abc'
              
              
                )
              
              
Expecting:
    
              
                'abc'
              
              
ok
1 items had no tests:
    test_string_lower
1 items passed all tests:
   3 tests 
              
                in
              
               test_string_lower.string_lower
3 tests 
              
                in
              
               2 items.
3 passed and 0 failed.
Test passed.

            
          

可以看到,程序测试的背后还是发生了很多事。接着,我们尝试着程序出错的情况,比如我们不小心把函数的返回写成了:

            
              
                return
              
               string
              
                .
              
              upper
              
                (
              
              
                )
              
            
          

这其实是返回输入字符串的大写了,而我们测试的实例却返回了输入字符串的小写,再运行该脚本(加上参数 -v ),输出的结果如下:

            
              Failed example:
    string_lower
              
                (
              
              
                'abc'
              
              
                )
              
              
Expected:
    
              
                'abc'
              
              
Got:
    
              
                'ABC'
              
              
1 items had no tests:
    test_string_lower
**********************************************************************
1 items had failures:
   3 of   3 
              
                in
              
               test_string_lower.string_lower
3 tests 
              
                in
              
               2 items.
0 passed and 3 failed.
***Test Failed*** 3 failures.

            
          

这时候,程序测试失败,它不仅捕捉到了bug,还清楚地指出错误出在什么地方。我们不难把这个程序修改过来。
  关于doctest模块的更详细的使用说明,可以参考网址:https://docs.python.org/2/library/doctest.html 。

unittest

   unittest类似于流行的Java测试框架JUnit,它比doctest更灵活,更强大,能够帮助你以结构化的方式来编写庞大而详尽的测试集。
  我们以一个简单的示例入手,首先我们编写my_math.py脚本,代码如下:

            
              
                # -*- coding: utf-8 -*-
              
              
                def
              
              
                product
              
              
                (
              
              x
              
                ,
              
               y
              
                )
              
              
                :
              
              
                '''
    :param x: int, float
    :param y: int, float
    :return:  x * y
    '''
              
              
                return
              
               x 
              
                *
              
               y

            
          

该函数实现的功能为:输入两个数x, y, 返回这两个数的乘积。接着是test_my_math.py脚本,完整的代码如下:

            
              
                import
              
               unittest
              
                ,
              
               my_math


              
                class
              
              
                ProductTestcase
              
              
                (
              
              unittest
              
                .
              
              TestCase
              
                )
              
              
                :
              
              
                def
              
              
                setUp
              
              
                (
              
              self
              
                )
              
              
                :
              
              
                print
              
              
                (
              
              
                'begin test'
              
              
                )
              
              
                def
              
              
                test_integers
              
              
                (
              
              self
              
                )
              
              
                :
              
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                -
              
              
                10
              
              
                ,
              
              
                10
              
              
                )
              
              
                :
              
              
                for
              
               y 
              
                in
              
              
                range
              
              
                (
              
              
                -
              
              
                10
              
              
                ,
              
              
                10
              
              
                )
              
              
                :
              
              
                p 
              
                =
              
               my_math
              
                .
              
              product
              
                (
              
              x
              
                ,
              
               y
              
                )
              
              
                self
              
                .
              
              assertEqual
              
                (
              
              p
              
                ,
              
               x
              
                *
              
              y
              
                ,
              
              
                'integer multiplication failed'
              
              
                )
              
              
                def
              
              
                test_floats
              
              
                (
              
              self
              
                )
              
              
                :
              
              
                for
              
               x 
              
                in
              
              
                range
              
              
                (
              
              
                -
              
              
                10
              
              
                ,
              
              
                10
              
              
                )
              
              
                :
              
              
                for
              
               y 
              
                in
              
              
                range
              
              
                (
              
              
                -
              
              
                10
              
              
                ,
              
              
                10
              
              
                )
              
              
                :
              
              
                x 
              
                =
              
               x
              
                /
              
              
                10
              
              
                y 
              
                =
              
               y
              
                /
              
              
                10
              
              
                p 
              
                =
              
               my_math
              
                .
              
              product
              
                (
              
              x
              
                ,
              
               y
              
                )
              
              
                self
              
                .
              
              assertEqual
              
                (
              
              p
              
                ,
              
               x 
              
                *
              
               y
              
                ,
              
              
                'integer multiplication failed'
              
              
                )
              
              
                if
              
               __name__ 
              
                ==
              
              
                '__main__'
              
              
                :
              
              
    unittest
              
                .
              
              main
              
                (
              
              
                )
              
            
          

函数unittest.main负责替你运行测试:在测试方法前执行setUp方法,示例化所有的TestCase子类,并运行所有名称以test打头的方法。assertEqual方法检车指定的条件(这里是相等),以判断指定的测试是成功了还是失败了。
  接着,我们运行前面的测试,输出的结果如下:

            
              begin 
              
                test
              
              
.begin 
              
                test
              
              
                .
              
              
----------------------------------------------------------------------
Ran 2 tests 
              
                in
              
               0.001s

OK

            
          

可以看到,该程序运行了两个测试,每个测试前都会输出’begin test’, . 表示测试成功,若测试失败,则返回的是 F
  接着模拟测试出错的情形,将my_math函数中的product方法改成返回:

            
              
                return
              
               x 
              
                +
              
               y

            
          

再运行测试脚本,输出的结果如下:

            
              begin 
              
                test
              
              
Fbegin 
              
                test
              
              
F

              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
FAIL: test_floats 
              
                (
              
              __main__.ProductTestcase
              
                )
              
              
----------------------------------------------------------------------
Traceback 
              
                (
              
              most recent call last
              
                )
              
              :
  File 
              
                "test_my_math.py"
              
              , line 20, 
              
                in
              
               test_floats
    self.assertEqual
              
                (
              
              p, x * y, 
              
                'integer multiplication failed'
              
              
                )
              
              
AssertionError: -2.0 
              
                !=
              
               1.0 
              
                :
              
               integer multiplication failed


              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
                ==
              
              
FAIL: test_integers 
              
                (
              
              __main__.ProductTestcase
              
                )
              
              
----------------------------------------------------------------------
Traceback 
              
                (
              
              most recent call last
              
                )
              
              :
  File 
              
                "test_my_math.py"
              
              , line 12, 
              
                in
              
               test_integers
    self.assertEqual
              
                (
              
              p, x*y, 
              
                'integer multiplication failed'
              
              
                )
              
              
AssertionError: -20 
              
                !=
              
               100 
              
                :
              
               integer multiplication failed

----------------------------------------------------------------------
Ran 2 tests 
              
                in
              
               0.001s

FAILED 
              
                (
              
              failures
              
                =
              
              2
              
                )
              
            
          

两条测试都未通过,返回的是 F ,并帮助你指出了错误的地方,接下来,你应该能快速地修复这个bug。
  关于unittest模块的更加详细的说明,可以参考网址: https://docs.python.org/3/library/unittest.html 。

总结

  本文介绍了两个Python中的测试工具: doctest和unittest,并配以简单的例子来说明这两个测试模块的使用方法,希望能对读者有所帮助~

注意:不妨了解下笔者的微信公众号: Python爬虫与算法(微信号为:easy_web_scrape), 欢迎大家关注~


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论