从开源项目看 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++的实现进行简要的分析,作为学习记录备份. 基本 ...
随机推荐
- 验证Oracle处理速度
(这是2009年写的东西了,在网上看到有人对数据库批量操作的'速度'比较关注,于是就把这篇老文章整理了一下) 一.环境及前提 在244上(一台稍好一些的机器,做了RAID,机械硬盘,Raid几忘了), ...
- DNA序列对齐问题
问题描述: 该问题在算法导论中引申自求解两个DNA序列相似度的问题. 可以从很多角度定义两个DNA序列的相似度,其中有一种定义方法就是通过序列对齐的方式来定义其相似度. 给定两个DNA序列A和B,对齐 ...
- Android开发之漫漫长途 Ⅳ——Activity的显示之ViewRootImpl初探
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- 关于帧动画steps属性的理解
CSS3的Animation有八个属性 animation-name animation-duration animation-delay animation-iteration-count anim ...
- [转]我在面试.NET/C#程序员时会提出的问题
http://blog.zhaojie.me/2011/03/my-interview-questions-for-dotnet-programmers.html 说起来我也面试过相当数量的.NET( ...
- Windows下pycharm远程连接服务器调试-tensorflow无法加载问题
最近打算在win系统下使用pycharm开发程序,并远程连接服务器调试程序,其中在import tensorflow时报错如图所示(在远程服务器中执行程序正常): 直观错误为: ImportError ...
- 父类清除浮动的原因、(清除浮动代码,置于CSS中方便调用)
浮动因素在静态网页制作中经常被应用到,比如要让块级元素不独占一行,常常应用设置float的方式来实现.但是应用的时候会发现,设置了子类浮动后,未给父类清除浮动,这样就会造成一下问题: 1.浮动的元素会 ...
- geotrellis使用(三十五)Cesium加载geotrellis TMS瓦片
前言 做任何事情都不是想象中的那么简单.好久没有更新技术博客了,跟最近瞎忙有很大关系,虽说是瞎忙也抽空研究了些技术. 主要是前端渲染,像原生的WebGL和Cesium.WebGL写了几篇博客,自我感觉 ...
- 玩转html
简介 CSS 是什么? CSS是Cascading Style Sheets的简称,中文称为层叠样式表. 作用 能够对网页中元素位置的排版进行像素级精确控制,支持几乎所有的字体字号样式,拥有对网页对象 ...
- Servlet,JSP 中的中文乱码问题以及解决方案
问题描述: 在Servlet,JSP 传递数据中,英文无影响,而中文有时候就会出现乱码. 解决方案: 相同的编码: 同一个项目中的每个文件应当设置和保存相同的编码方式,如: html中 <met ...