共计 3679 个字符,预计需要花费 10 分钟才能阅读完成。
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 单元测试
咱们明天就解说到这啦
点击进入取得更多技术信息~~