从开源项目看 Python 单元测试
我觉得以前在我开发程序的时候,除了文档,可能单元测试是另外一个让我希望别人都写,但是自己又一点都不想写的东西。但是,随着开发程序的增多,以及自己对 Bug 的修改的增多,我发现,UT 在很大程度上是对我有利的,虽然带来的结果就是可能我的 Dev 时间会增加 20-40% 左右,但是,相比较于一段时间之后突然冒出来一个 Bug,让你摸不着头脑;或者说突然一个接一个的 Bug 在你转测试之后提过来,写 UT 的幸福感和自豪感明显是更高的。
就我目前而言,我认为写单元测试有这么几个好处:
- 帮助减小代码的耦合度,这样你才能更容易得编写 UT
- 理清代码的模块依赖,这样你才能在 UT 中知道哪些东西要 Mock,哪些东西要 Stub
- 保持接口的干净和明朗,UT 就是针对接口编程,Input 和 Ouput 都需要明确
- UT 是一个自诠释的文档,别人可以通过你的 UT 来学习你的接口使用方式
这里我需要提出一点的就是,一般而言,我很难做到 Test First,也就是所谓的先完成 UT 代码的编写,然后再写实现代码。当然,这不是说不行,就以目前的经历来说,这做法欠妥,一个很重要的原因是项目周期的把控,如果你 UT First,万一后面你时间不够实现 Logical Code 了怎么办?光有 UT 并不能让你的整个 Project 跑起来。所以,一般来说,我经历的大部分项目都是先 Run 起来,然后再通过 UT 保证目前的功能是正常的,并且可以保证在以后的维护和更新中,功能的正确性不会被破坏。
测试方法
学过完善的软件工程体系的同学都知道,软件测试是软件工程中非常重要的一环,甚至于可以说对于一个 Project,测试人员的参与度比 Developer 的高多了,我刚毕业那会,测试人员的参与度可以说是贯穿了全流程,从需求的提出到验收发布,这整个流程都有测试人员的参与,而 Developer,可能参与到"转测试"环境就差不多完了,所以测试工程也是一项非常复杂的学科。
测试覆盖
因为测试非常复杂,所以也是有很多方法论和实践的。就拿 UT 来说,对于代码我们可以有几个不同的测试角度。例如覆盖角度来说,我们就有语句覆盖,分支覆盖,条件覆盖,路径覆盖和循环覆盖;测试内容来说,我们又会分模块测试,数据结构测试,路径测试,错误处理测试和边界测试等等。对于这么多测试,其实我发现大部分开源项目都没有很严格得遵守这些理论,因为可能说随便一条理论在实践中都能让人抓狂。
其实在我见过的几个流行的开源项目中,基本上都是以语句覆盖为目标进行的,并且并不能达到 100%,所以更多得是以主要功能是正常的为目标进行 UT 测试的。以下是部分开源项目的测试结果:

除此之外,对于 UT 的增加是在 issue 的基础上建立的,也就说当有用户提了一个 issue 之后,Maintener 觉得这个 issue 是个问题,并且会影响到我这个项目,那么就会开发开发相应的 patch fix 它,并且补上 UT,这种情况也是比较常见,这样的话,渐渐地 UT 的覆盖率也就慢慢上去了。
测试方法
在测试中,我们的代码可能会有很多依赖,例如模块依赖,组件依赖等等,为了解决这些依赖,我们总要有一些方法来处理,这里就有两项经常使用的技术:Stub 和 Mock。
我以前喜欢说讲一个对象 Mock 掉,意思就是讲一个对象用自定义的模拟类替换掉,从而让我们可以自定义类的行为和输出,但是,我发现这其实在测试中是 Stub,所谓的 Stub 就是模拟测试代码调用的模块和组件,从而自定义被调用后的行为和输出;而相比之下,Mock 的功能是验证模板或者组件有没有被调用,很常见的例子就是邮件发送服务有没有被调用,有没有输出日志内容等等。关于 Stub 和 Mock 更多的内容介绍我推荐 Martin Folwer 的这篇文章:Mocks Aren't Stubs。
测试工具
在 Python 中,自身就带了类 XUnit 的 unittest 框架,使用也很简单,例如下面就是一个很简单的测试用例:

其实使用起来已经很简单了,但是 Python 的小伙伴还是嫌他又啰嗦又慢,所以你会发现 pytest 这个库很受欢迎。
pytest
pytest 作为一个单元测试框架,使用方法有多种,既可以和 python 自带的 unittest 类似,又可以很简单得就一个函数来写 UT;不仅开发效率会更高,而且执行效率也可以更高,其他优点就不啰嗦介绍了,官网里面都罗列了:pytest。
至于有多简单方便,你将下面这段代码保存到 test_sample.py
文件中,然后在对应的目录路径下执行 pytest
命令

执行之后你应该会发现:

对,你会发现,就这么简单得执行起来了。但是,很多同学还是不满于此,因为很多 Python 项目不仅仅适应于一个版本的 Python,所以就会有多一个 Python 版本的测试(Python 的又一坑,2.6/2.7/3.x/3.5 不兼容)。
tox
为了满足一个 Python 项目可以在多个 Python 版本中可以正常运行,很多人会使用 tox 进行不同环境下的兼容性测试,所以 tox 的功能就是环境管理和测试运行。关于 tox 的更多功能使用和细则可以参考一下 tox 官网:Tox。
tox 一般都会有一个 tox.ini 文件,例如一个简单的例子:

然后执行 tox
命令行工具就可以了,它就会找你机器上的各种环境,然后测试起来,最后的结果就有点类似于:

小结
单元测试是一种习惯,也是一种责任。通过单元测试,我们可以告诉别人我的代码是 Work 的,同时也给别人一种信任感,可以让别人相信你写的代码。同时,编写单元测试也是一项比较繁琐的事情,我们要处理依赖,考虑 Test Case,但是,这些过程都可以帮助我们更好得思考我们的项目和软件,从而让软件的结构和代码的质量提升一个台阶。
从开源项目看 Python 单元测试的更多相关文章
- 从开源项目看python代码注释
最近看了不少代码,也写了不少代码,所以在看和写之间发现了很多的问题,真的是很多,至少从我的认识来看,有几个地方有很大的改进空间,这里不准备把所有的问题都列举出来,所以就先挑选一个比较明显得来和大家聊聊 ...
- GitHub 上适合新手的开源项目(Python 篇)
作者:HelloGitHub-卤蛋 随着 Python 语言的流行,越来越多的人加入到了 Python 的大家庭中.为什么这么多人学 Python ?我要喊出那句话了:"人生苦短,我用 Py ...
- Python:渗透测试开源项目
Python:渗透测试开源项目[源码值得精读] sql注入工具:sqlmap DNS安全监测:DNSRecon 暴力破解测试工具:patator XSS漏洞利用工具:XSSer Web服务器压力测试工 ...
- 讲解开源项目:用 Python 生成有“灵魂”的二维码
本文作者:HelloGitHub-LITTLECHIEH 这是 HelloGitHub 推出的<讲解开源项目>系列,今天给大家推荐一个 Python 开源生成二维码的项目--qrcode ...
- Github上的python开源项目
Python开源项目,期待大家和我们一起共同维护 github排名榜单 https://github.com/trending github搜索榜单:https://github.com/search ...
- 教你阅读Python开源项目代码
为什么要阅读开源代码 阅读 Python 开源项目代码主要有如下三个原因: 在工作过程中遇到一些问题 Google 和 StackOverFlow 等网站找不到解决办法,只能去翻源码. 对某些项目或者 ...
- Python优秀开源项目Rich源码解析
这篇文章对优秀的开源项目Rich的源码进行解析,OMG,盘他.为什么建议阅读源码,有两个原因,第一,单纯学语言很难在实践中灵活应用,通过阅读源码可以看到每个知识点的运用场景,印象会更深,以后写代码的时 ...
- 【Java经验分享篇01】小白如何开始学会看开源项目?
目录 前言 1.理解开源 1.1.什么是开源? 1.2.开源的定义 1.2.1.开源软件优点 1.2.2.经典开源软件案例 1.3.关于开源协议 1.3.1.如何选择开源协议 2.如何查找开源项目 2 ...
- GTest Google的一种白盒单元测试框架 开源项目
GTest为google开源的白盒单元测试跨平台测试框架,含丰富的断言.类型参数化测试.死亡测试.以及其他的测试选项设置.文件保存等,以下将对该项目C++的实现进行简要的分析,作为学习记录备份. 基本 ...
随机推荐
- pandas数据结构练习题(部分)
更多函数查阅http://pandas.pydata.org/pandas-docs/stable/10min.htmlimport pandas as pd#两种数据结构from pandas im ...
- jumpserver安装详解
环境说明 主机为最小 安装的centos6.9 x86_64. [root@m01 ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [ro ...
- [DeeplearningAI笔记]ML strategy_2_3迁移学习/多任务学习
机器学习策略-多任务学习 Learninig from multiple tasks 觉得有用的话,欢迎一起讨论相互学习~Follow Me 2.7 迁移学习 Transfer Learninig 神 ...
- c++学习笔记---02---从一个小程序说起
从一个小程序说起 这一讲的主要目的是帮助大家在C语言的背景知识上与C++建立联系. 问题探索 问题:对一个整型数组求和. 要求:定义一个存储着 n 个元素的数组,要求用C语言完成这个任务. 赶紧的:大 ...
- SQL基本查询_多表查询(实验三)
SQL基本查询_多表查询(实验三) 题目要求(一) 针对emp.dept两表完成如下查询,并验证查询结果的正确性 使用显式内连接查询所有员工的信息,显示其编号.姓名.薪水.入职日期及部门名称: 使用隐 ...
- selenium-iframe操作
iframe,又叫浮动帧标记,是内嵌的网页元素,可以将一个html文件嵌入到另一个html文件中显示. 最典型的案例就是163邮箱登录:http://mail.163.com/,被绿色覆盖的部分即为i ...
- webpack学习笔记啊(幕课)
基础配置总结 webpack hello.js hello.bundle.js打包命令参数 --config filename : 指定其他名称做配置文件 --watch / -w : 监听文件改动, ...
- Jdbc访问数据库篇
一万年太久,只争朝夕 What JDBC 上部 JDBC(Java DataBase Connectivity)Java 数据库连接,主要提供编写 Java 数据库应用程序的 API 支持 java. ...
- 阿里云CentOS搭建系统
1.在阿里云网站上购买申请服务器. 2.通过Xshell连接服务器,并用root账户登入. 3.配置java开发环境:(也可以使用阿里云一键部署,自动配置并部署服务器) 一.安装jdk 1.查看Lin ...
- 前端面试题(6)图片格式jpg,gif,png-8,png-24的区别,及其各自的使用场景
Gif格式特点: 透明性,Gif是一种布尔透明类型,既它可以是全透明,也可以是全不透明,但是它并没有半透明(alpha透明). 动画,Gif这种格式支持动画. 无损耗性,Gif是一种无损耗的图像格式, ...