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

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

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

doctest

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

  我们先创建示例代码文件test_string_lower.py,完整代码如下:

  1. # -*- coding: utf-8 -*-
  2. def string_lower(string):
  3. '''
  4. 返回一个字符串的小写
  5. :param string: type: str
  6. :return: the lower of input string
  7. >>> string_lower('AbC')
  8. 'abc'
  9. >>> string_lower('ABC')
  10. 'abc'
  11. >>> string_lower('abc')
  12. 'abc'
  13. '''
  14. return string.lower()
  15. if __name__ == '__main__':
  16. import doctest, test_string_lower
  17. 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,输出的结果如下:

  1. Trying:
  2. string_lower('AbC')
  3. Expecting:
  4. 'abc'
  5. ok
  6. Trying:
  7. string_lower('ABC')
  8. Expecting:
  9. 'abc'
  10. ok
  11. Trying:
  12. string_lower('abc')
  13. Expecting:
  14. 'abc'
  15. ok
  16. 1 items had no tests:
  17. test_string_lower
  18. 1 items passed all tests:
  19. 3 tests in test_string_lower.string_lower
  20. 3 tests in 2 items.
  21. 3 passed and 0 failed.
  22. Test passed.

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

  1. return string.upper()

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

  1. Failed example:
  2. string_lower('abc')
  3. Expected:
  4. 'abc'
  5. Got:
  6. 'ABC'
  7. 1 items had no tests:
  8. test_string_lower
  9. **********************************************************************
  10. 1 items had failures:
  11. 3 of 3 in test_string_lower.string_lower
  12. 3 tests in 2 items.
  13. 0 passed and 3 failed.
  14. ***Test Failed*** 3 failures.

这时候,程序测试失败,它不仅捕捉到了bug,还清楚地指出错误出在什么地方。我们不难把这个程序修改过来。

  关于doctest模块的更详细的使用说明,可以参考网址:https://docs.python.org/2/library/doctest.html

unittest

   unittest类似于流行的Java测试框架JUnit,它比doctest更灵活,更强大,能够帮助你以结构化的方式来编写庞大而详尽的测试集。

  我们以一个简单的示例入手,首先我们编写my_math.py脚本,代码如下:

  1. # -*- coding: utf-8 -*-
  2. def product(x, y):
  3. '''
  4. :param x: int, float
  5. :param y: int, float
  6. :return: x * y
  7. '''
  8. return x * y

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

  1. import unittest, my_math
  2. class ProductTestcase(unittest.TestCase):
  3. def setUp(self):
  4. print('begin test')
  5. def test_integers(self):
  6. for x in range(-10, 10):
  7. for y in range(-10, 10):
  8. p = my_math.product(x, y)
  9. self.assertEqual(p, x*y, 'integer multiplication failed')
  10. def test_floats(self):
  11. for x in range(-10, 10):
  12. for y in range(-10, 10):
  13. x = x/10
  14. y = y/10
  15. p = my_math.product(x, y)
  16. self.assertEqual(p, x * y, 'integer multiplication failed')
  17. if __name__ == '__main__':
  18. unittest.main()

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

  接着,我们运行前面的测试,输出的结果如下:

  1. begin test
  2. .begin test
  3. .
  4. ----------------------------------------------------------------------
  5. Ran 2 tests in 0.001s
  6. OK

可以看到,该程序运行了两个测试,每个测试前都会输出'begin test',.表示测试成功,若测试失败,则返回的是F

  接着模拟测试出错的情形,将my_math函数中的product方法改成返回:

  1. return x + y

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

  1. begin test
  2. Fbegin test
  3. F
  4. ======================================================================
  5. FAIL: test_floats (__main__.ProductTestcase)
  6. ----------------------------------------------------------------------
  7. Traceback (most recent call last):
  8. File "test_my_math.py", line 20, in test_floats
  9. self.assertEqual(p, x * y, 'integer multiplication failed')
  10. AssertionError: -2.0 != 1.0 : integer multiplication failed
  11. ======================================================================
  12. FAIL: test_integers (__main__.ProductTestcase)
  13. ----------------------------------------------------------------------
  14. Traceback (most recent call last):
  15. File "test_my_math.py", line 12, in test_integers
  16. self.assertEqual(p, x*y, 'integer multiplication failed')
  17. AssertionError: -20 != 100 : integer multiplication failed
  18. ----------------------------------------------------------------------
  19. Ran 2 tests in 0.001s
  20. FAILED (failures=2)

两条测试都未通过,返回的是F,并帮助你指出了错误的地方,接下来,你应该能快速地修复这个bug。

  关于unittest模块的更加详细的说明,可以参考网址: https://docs.python.org/3/library/unittest.html

总结

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

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

Python中的测试工具的更多相关文章

  1. 基于Python的XSS测试工具XSStrike使用方法

    基于Python的XSS测试工具XSStrike使用方法 简介 XSStrike 是一款用于探测并利用XSS漏洞的脚本 XSStrike目前所提供的产品特性: 对参数进行模糊测试之后构建合适的payl ...

  2. Apache中压力测试工具ab的操作说明

    1.压力测试工具ab(ApacheBench)的简单说明 1)     网站性能压力测试是性能调优过程中必不可少的一环.只有让服务器处在高压情况下才能真正体现出各种设置所暴露的问题.Apache中有个 ...

  3. 使用Python学习selenium测试工具-4:查找元素

    转自:https://blog.csdn.net/wd168/article/details/51819930 web通常包含了Hyper Text Markup Language (HTML).Ca ...

  4. 【转】使用Python学习selenium测试工具

    出处:https://my.oschina.net/u/1433482/blog/633231?fromerr=vaxqh9bn

  5. github渗透测试工具库

    本文作者:Yunying 原文链接:https://www.cnblogs.com/BOHB-yunying/p/11856178.html 导航: 2.漏洞练习平台 WebGoat漏洞练习平台: h ...

  6. github渗透测试工具库[转载]

    前言 今天看到一个博客里有这个置顶的工具清单,但是发现这些都是很早以前就有文章发出来的,我爬下来后一直放在txt里吃土.这里一起放出来. 漏洞练习平台 WebGoat漏洞练习平台:https://gi ...

  7. Python中多使用迭代器

    英文原文出处:Use More Iterators 本文介绍将代码转换为使用迭代器的原因和实用技巧. 我最喜欢的Python语言的特色之一是生成器,它们是非常有用的,然而当阅读开源代码时,我很少遇到它 ...

  8. Python渗透测试工具合集

    摘自:http://www.freebuf.com/tools/94777.html 如果你热爱漏洞研究.逆向工程或者渗透测试,我强烈推荐你使用 Python 作为编程语言.它包含大量实用的库和工具, ...

  9. python渗透测试工具集合

    作者:一起学习Python 原文链接:https://zhuanlan.zhihu.com/p/21803985 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 在进行漏洞研究. ...

随机推荐

  1. Python高级数据结构-Collections模块

    在Python数据类型方法精心整理,不必死记硬背,看看源码一切都有了之中,认识了python基本的数据类型和数据结构,现在认识一个高级的:Collections 这个模块对上面的数据结构做了封装,增加 ...

  2. Feign超时设置

    转-原文:https://xli1224.github.io/2017/09/22/configure-feign/ 在分析 Feign 源码的时候,我们看到 Feign 构建代理对象是分了几层的,一 ...

  3. PAT甲级专题|链表

    PAT链表专题 关于PAT甲级的链表问题,主要内容 就是"建立链表" 所以第一步学会模拟链表,pat又不卡时间,这里用vector + 结构体,更简洁 模拟链表的普遍代码 cons ...

  4. 使用echarts常用问题总结

    1,echarts配合element ui的抽屉插件出现报错,上次解决方法是使用element ui 抽屉的open事件,让在打开事件重新加载,我们项目的需求是点击某个数据,要传递这条数据包含的其他值 ...

  5. Maven项目多环境之间的配置文件的切换

    前言:对于一个项目,开发和生产环境之间会使用不同的配置文件,最简单的例子就是数据库连接池的配置了.当然,可以在打包上线前对配置文件进行替换,不过这也太low了吧. 简单的pom.xml中的配置内容 比 ...

  6. DevOps on DevCloud|如何采用流水线践行CI/CD理念【华为云技术分享】

    [摘要] 持续集成/持续交付(CI/CD,Continuous Integration/Continuous Deployment)在DevOps CMALS理念中具有支柱性地位,因而CI/CD流水线 ...

  7. C# 自然周,月,季度计算。

    /// <summary> /// 判断时间是否和服务器时间是一天 /// </summary> /// <param name="cs">&l ...

  8. python笔记02

    day02笔记记录 一.今日摘要 循环.字符串格式化.运算符.编码.博客. 二.内容回顾 (一)计算机基础 计算机由硬件和软件组成.传统计算机的硬件一般有输入单元.输出单元,算数逻辑单元.控制单元及记 ...

  9. Mybatis动态查询

    需要导入的jar包: 实体类User: package com.bjsxt.pojo; import java.io.Serializable; public class User implement ...

  10. 洛谷 题解 P1600 【天天爱跑步】 (NOIP2016)

    必须得说,这是一道难题(尤其对于我这样普及组205分的蒟蒻) 提交结果(NOIP2016 天天爱跑步): OJ名 编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间 Libre ...