Are you ready?

↓↓↓

今天的课程为《 Python单元测试》,内容共分为三个部分:单元测试的概念、工具与方法、Coverage 统计单元测试覆盖率的工具和Mock 简化单元测试的工具。

单元测试的概念、工具与方法

单元测试的概念

测试具有许多种不同的类型,比如说单元测试、模块测试、联调测试、系统测试、交付测试等。在这些测试之中,单元测试是最先要完成的。单元测试通常是由开发者去完成,用来验证代码中的函数是否符合预期。因此,它聚焦于函数的逻辑以及核心的算法是否正确。通常而言,一个单元测试用例是用于判断在某个特定条件或场景下,某个特定函数的行为。

单元测试的意义

单元测试的意义包括两个方面。

(1)质量

①单元测试主要针对函数,颗粒度小、测试针对性强,bug更容易暴露;

②由于单元测试覆盖面较窄,无需考虑其它函数或者所依赖的模块,所以它的场景易构造,核心功能验证更充分;

③进行单元测试保证整体代码结构良好,使代码就具有较高的可测性和可维护性。

(2)效率

单元测试能够提高开发效率,主要表现在:

①单元测试进行的时间较早,测试场景构建快,可有效减少调试时间。

②由于单元测试只针对修改的代码展开测试,无需考虑额外内容,所以在较短时间内即可把预期的逻辑测试充分。

③单元测试能够在项目开发初期发现的bug,bug发现的时间越早,所带来的收益越大。由于尽早发现bug能够节省整个项目开发的时间,所以单元测试可加快开发效率,缩短开发周期。

单元测试框架

(1)测试框架选择

在进行单元测试的时候,我们需要测试框架作为工具。一个良好的测试框架能够让测试工作事半功倍,此处我们介绍三个框架。

①Unittest是Python标准库中原生自带的,它的好处在于无兼容性问题,是其他框架的基础;不足之处在于编码略显繁琐,入门门槛稍高。

②Pytest的好处在于编码简洁、生态好、插件丰富、使用人数多;不足之处在于他属于第三方库,使用前另需提前安装。

③Nose2能够兼容Unittest,也属于第三方库,需要安装,但是与Pytest相比,它迭代缓慢,使用人数少。

在这里我们选择Unittest作为单元测试的框架,原因有二:首先,作为Python标准库中原生自带的框架,Unittest无兼容性问题;其次,第三方库难以保证长期快速迭代,易过时。

(2)Unitest的基础概念

在做单元测试之前,需要先了解一下Unittest的几个基础概念。

①Test(测试用例),针对一个特定场景,特定目的具体测试过程。

比如说一个函数通过一组输入测试它,就是一个测试用例;如果一个函数通过三组输入来测试,即为三个测试用例。

②TestCase(测试类),可以包含同一个测试对象的多个测试用例。

如果一个函数通过三组输入来测试,也就是三个测试用例,这三个测试用例可以合成为一个测试类。

③TestSuite(测试集),可以包含多个测试类的多个测试用例。

④Assertion(断言),必须使用断言判断测试结果。

⑤TestFixture,为测试做统一的准备和清除工作,通常是初始化,连接数据库,准备数据,断开数据库,清除现场等。

扩展来说,TestFixture有四种最常使用的作用范围,分别为:

→ setUp:在测试类的每个测试用例执行前执行。

→ teardown:在测试类的每个测试用例执行后执行。

→ setUpClass:在测试类的第一个测试用例执行前执行。

→ tearDownClass:在测试类的最后一个测试用例执行后执行。

TestFixture可以让单元测试代码更简单,但并非必须使用,也不要求配对出现。

单元测试的规范

想要做好单元测试,必须遵循一定的规范。下面介绍一下单元测试涉及的规范。

(1)所有的单元测试必须使用断言(assert)判断结果,禁止出现无断言的测试用例;

使用断言,不但有利于他人理解,而且一旦出现不符合预期的情况,可以立即找出问题。

可以使用assertEqual, assertNotEqual 来判断相等或不相等,assertTrue,assertFalse 来判断Boolean, assertRaises 判断抛出的异常是否符合预期。

(2)测试用例需要具有自表述能力,达到见名知意。

比如命名test_login_with_invalid_password(),通过它的名字便可知它是用一个非法的密码去测试登录功能,具有自表述能力;但是如果命名为 test_login_case_(),名字减少了很多信息,难以得知它具体在做什么,不具有自表述能力。

(3)测试用例之间相互独立,不应相互依赖、相互调用。

(4)一个测试用例只测一个函数。一个测试用例里面可以包含这一个函数的多个场景,但不能包含有多个参数的函数。原因在于,复杂测试用例出现错误时,无法定位问题的出处。

单元测试对编码的要求

单元测试中代码需保持一致性,尽量不要出现结果不一致的情况。假设有的代码会带来不一致性,导致单元测试无法稳定运行。针对这种情况,有两种解决方案:第一,将带来不一致性的代码抽取出来,把它作为一种变量传入我们需要调用或使用一致性变量的时候;第二,借助第三部分即将讲到的一个工具——mock——来解决这种问题。

Coverage 统计 单元测试覆盖率的工具

单元测试做完之后如何评价我们单元测试的效果。此时需要用到覆盖率工具,即Coverage。Coverage是一个第三方的工具,需要提前下载安装。

(1)统计覆盖率方法

把python替换为coverage run-branch,然后会生成coverage文件,文件里会记录所有我们需要的覆盖率信息。

(2)打印覆盖率信息

执行coverage report-m 命令,读取当前目录下.coverage文件,打印覆盖率信息。输出Stmts(总行数), Miss(未覆盖行数), Branch(总分支数), BrPart (未覆盖分支数), Cover(覆盖率) , Missing(未覆盖具体信息)等信息。

(3)覆盖率中排除某些文件

执行coverage report-m—omit=file 1[,file 2,……] 命令, 在统计并打印覆盖率时,排除某些文件。若有多个文件用逗号分隔。

(4)生成HTML格式的覆盖率信息

针对代码量较大,查找覆盖率信息难度较大、耗时较长的情况,执行coverage html [–omit=file1[,file2,……]]命令,将覆盖率信息以html格式显示。

Mock 简化单元测试的工具

使用mock工具的原因与其功能

Mock基于实际进行单元测试的场景而产生,以下三类场景非常具有代表性:

①构造模块。需要测试模块A,但它要调用的模块B还未开发,可是测试却不容推迟、需按时进行,面对这种情况,我们可以使用Mock生成一个还未写完的代码,即可进行相应的测试。

②改变函数逻辑。代码中含有结果不可预知的代码,例如time.time()(时间), random.random()(随机数)。Mock可以改变含有结果不可预知代码的函数的逻辑,强行让其返回我们想要的返回值,使其结果可预知。

③减少依赖。在所有模块代码都已完成,但无法保证代码稳定性的情况下。针对其他模块的质量不可靠的情况,可通过Mock工具构造一个相对稳定的模块,从而规避其他模块的问题。

Mock使用场景

通过以下10个场景来讲述Mock的常见用法。

场景01:通过 return_value,Mock可以强行修改,永远返回我们想要的返回值,支持的类型包括string,number,Boolean,list,dict等。

场景02:将前一个例子的实例名改为类名,可实现替换类方法的返回值。

场景03:通过 side_effect,根据调用次数返回想要的结果,当超出调用次数时抛StopIteration 异常。

场景04:通过 side_effect可以完全修改函数的逻辑,使用另一个函数来替换它,根据参数返回想要的结果。

场景05:通过 side_effect抛出想要的异常或错误。

场景06:针对需要mock在特定要求下生效的情况,通过with.patch.object设定一个作用域以达到限制mock作用域的目的。

场景07:获取调用信息,如函数是否被调用、函数被调用的次数、函数被调用的形式、函数调用的参数等。

场景08:通过create_autospec在返回值改变的同时,确保api不会因mock而改变。

场景09:针对需要调用的函数、调用的接口完全没有开发的情况,可以通过Mock从零构造依赖模块从而完成测试。

场景10 :替换函数调用链。比如说用popen去执行一个命令,然后用read函数把它读取出来,再用split去做切分,这就是一个函数调用链(os.popen(cmd).read().split())。

Mock 对编码的要求

在模块引入方式上,推荐以import XXX的形式引入,以XXX.func()形式调用,不要from.xxx import *,因为需要一个链条指向它,否则无法达到我们的预期。

关于Python单元测试

我们今天就讲解到这啦

点击进入获得更多技术信息~~

Python单元测试最佳实践相关推荐

  1. 领域驱动设计之单元测试最佳实践(二)

    领域驱动设计之单元测试最佳实践(一) 介绍完了DDD案例,我们终于可以进入主题了,本方案的测试代码基于Xunit编写,断言组件采用了FluentAssertions,类似的组件还有Shouldly.另 ...

  2. @sql 单元测试_SQL单元测试最佳实践

    @sql 单元测试 SQL unit testing is a testing method which allows us to test the smallest, atomic programm ...

  3. vim写python_用 Vim 写 Python 的最佳实践

    先来晒个图: 对于一些 Python 的小项目,使用 vim 是一个不错的选择.本文内容整理自我在知乎的回答 用 Vim 写 Python 的最佳实践是什么?,下面的内容是对知乎旧有回答的一个补充,尤 ...

  4. 30个python的最佳实践,快去试试吧!

    30 个 Python 的最佳实践.小贴士和技巧 原:作者 | Erik-Jan van Baaren 原:译者 | 弯月,责编 | 屠敏 以下为译文: 1. Python 版本 在此想提醒各位:自2 ...

  5. 30 个 Python 的最佳实践、小贴士和技巧

    作者 | Erik-Jan van Baaren 译者 | 弯月,责编 | 屠敏 出品 | CSDN(ID:CSDNnews) 以下为译文: 元旦过完了,我们都纷纷回到了各自的工作岗位.新的一年新气象 ...

  6. Virtualenv or Anaconda?Python虚拟环境最佳实践

    最近同时在Window和Linux上交替使用Virtualenv和Anaconda,期间一直在思考两种工具哪一个更好?是否可以统一使用其中一个完成所有Python项目的环境构建?针对这个问题,本文做了 ...

  7. python编码最佳实践之总结

    2019独角兽企业重金招聘Python工程师标准>>> 相信用python的同学不少,本人也一直对python情有独钟,毫无疑问python作为一门解释性动态语言没有那些编译型语言高 ...

  8. Junit内部解密之四: Junit单元测试最佳实践

    我们做使用Junit工具来做单页测试或接口测试时,需要注意一些问题,包括我们的编码规范,test规范,以及编写测试代码的策略,以下个人的总结. 1.为还没有实现的测试代码抛出一个异常.这就避免了该测试 ...

  9. 30 个 Python 的最佳实践、小贴士和技巧,不可错过哟!

    1. Python 版本 在此想提醒各位:自2020年1月1日起,Python 官方不再支持 Python 2.本文中的很多示例只能在 Python 3 中运行.如果你仍在使用 Python 2.7, ...

最新文章

  1. 使用Ext Form自动绑定Html中的Form元素
  2. (七)渐变 矩形渐变 放射渐变
  3. C语言学习笔记(一)_hello world
  4. Codeforces Round #700 (Div. 2) D1 D2. Painting the Array 思维
  5. android 技能标签功能_iOS和Android用户体验设计差异
  6. drbd(三):drbd的状态说明
  7. arm-hisiv100nptl-linux-gcc编译boa和移植
  8. wincc怎么做数据库_关于WINCC通过PLCSIM来进行仿真中要怎么设置?
  9. [原创]Datagrid和Button控件
  10. python 官方 中文 文档
  11. cpp设计并实现大整数
  12. 重温张欣穗购书衷心与申霞艳,张鸿等名师座谈《千万与春住》二零一九年六月二十四日
  13. Ubuntu18.04之lightdm取代gdm
  14. can‘t connect to mysql server on localhost解决办法。 net start mysql——无法启动服务,原因可能是已被禁用或与其相关联的设备没有启动。
  15. CSUOJ1238--兵临城下
  16. 【自然语言处理】ChatGPT 相关核心算法
  17. Linux上可用的Markdown编辑器
  18. 【Android】打包生成APK教程
  19. MATLAB中的eig函数
  20. python 日历壁纸_Excel+Python=精美DIY壁纸日历

热门文章

  1. linux命令:java程序后台运行
  2. shell如果文件夹不存在则创建
  3. 使用docker-compose配置redis服务
  4. Ansible 介绍和架构、特性
  5. Hadoop存算分离实现方案探讨
  6. 【收藏】Hadoop解决Could not locate executable null\bin\winutils.exe in the Hadoop binaries.问题
  7. 【网址收藏】helm charts github地址
  8. idea安装golang插件(仅针对2017年之前的idea版本)
  9. springboot集成kafka及kafka web UI的使用
  10. Linux centos 6.7 设置主机名