百度高效研发实战训练营-Step3

、# 百度高效研发实战训练营-Step3


3.1 质量意识

关于本部分,将从以下几点进行介绍:

3.1.1 质量的基本概念

意识的树立,源于认识的提高。
首先介绍质量的基本概念,主要包括以下内容:

1 质量重要性的认识

随着技术的更新,市场竞争的加剧,质量问题成为了困扰不少企业的一大难题,也给一些企业造成了巨大的损失,这也使得项目质量的重要性不断凸显。

通过对于这些失败案例的分析,不难发现,项目的质量保证是需要项目全体成员参与的重要工作,只有在项目团队成员的共同努力下,才能有效保证项目的质量,为企业和社会创造价值。

项目管理三要素为质量、时间、成本,三个要素缺一不可,相互制约。
一昧追求某一要素的做法,是不明智的。

一个成功的项目,必然是在三者的取舍间,达成了一个平衡。

2 质量保证和测试的关系

质量问题有很多种,常见的有代码缺陷、产品缺陷、Bug、用户体验差、性能差、服务不稳、安全问题、可兼容性差等。

我们经常通过测试来发现问题,并将发现的问题,分为功能性类问题和用户体验评估类问题。

测试工作是质量保证工作汇总的重要一环,但是我们也应该认识到,质量保证工作不能只依靠测试的反馈,而应该贯穿项目开发的整个过程。

3 Bug的基本认识

Bug是程序中的缺陷和问题,属于功能性测试类问题的范畴。
Bug是一种很常见的质量问题,也是我们在开发中应该尽量减少或避免的质量问题。

Bug的修复,有一套完整的规定流程:
首先,在测试人员或用户发现Bug后,将其置为激活状态。
开发人员在收到激活类状态的Bug后,对其进行修复,此时Bug状态为处理中。

修复完成后,开发人员将其置为解决状态,测试人员再对其进行验证,若通过,则将其关闭;否者,重新激活Bug即重启状态,交予开发人员继续修复,直至验证通过。

从这一流程可以看到,Bug有以下五种状态:

  • Open(激活)
  • In Process(处理中)
  • Resolved(解决)
  • Close(关闭)
  • Reopen(重启)

我们知道,Bug的生命周期是有一定规律的。
以传统软件中的瀑布模型举例,85%的问题在项目初期的编码阶段引入,在后期测试阶段,发现Bug数量会逐渐增多,与之对应的修复成本也会急剧增加,从此可见,降低修复成本最有效的方式,就是在Bug加入的阶段就及时发现并修复Bug。

3.1.2 Bug提交方法

Bug提交需要反馈渠道,Bug的反馈渠道分为内部反馈渠道和外部用户反馈渠道。
内部用户反馈渠道,包括产品Icafe空间、产品论坛、Bugs邮件组、Bugs平台。

外部用户反馈渠道,包括产品自身反馈渠道和产品接入反馈渠道。

Bug的提交,有严格的格式要求。

提交的Bug反馈应包括以下七个方面的内容:

  • 标题
  • 问题描述
  • 复现步骤
  • 能否复现
  • 问题来源
  • 问题影响
  • 补充描述

正确提交Bug,可以确保负责人能够清晰了解问题,直接进行数据挖掘,找到Bug所有的属性,便于后续维护工作的开展。

3.1.3 质量保证在项目各阶段的实现

质量的保证不能仅仅依靠测试人员,而是需要贯穿项目的各个阶段。
Bug的发现和修复是项目质量保证的一个重要方面,但质量保证工作绝不仅仅是修复Bug这么简单。

项目的开发整体路径,包括:

  • 需求阶段
  • 设计阶段
  • 开发阶段
  • 测试阶段
  • 发布阶段
  • 上线阶段
  • 线上阶段

在一个项目开发的各个不同阶段,质量保证工作的要求和思路,均有一定的不同。

下面来展现质量保证工作在各个阶段的具体实现

1 需求与设计阶段的质量保证工作

需求与设计阶段,是项目开始的重要阶段。
只有从客户真正的需求出发,才能设计出真正令客户满意的产品。

在这一阶段,质量保证工作的关键点有三:

  • (1)需求评审
    站在用户的角度思考和挖掘需求,是设计和开发的前提性条件。
  • (2)需求的变更管理
    用户的需求始终在改变,建立一套完善机制去及时适应需求的变更十分重要。
  • (3)设计评审
    通过评审需求的可行性和设计的相关风险,可以极大降低设计风险,避免人力浪费。

2 开发与测试阶段的质量保证工作

在开发阶段,质量保证工作,最重要的有两点,单元测试和代码评审。

单元测试的作用有很多,主要有:

  • ①调试代码,确保代码实时可编译
  • ②验证逻辑,减少代码中的Bug
  • ③回归测试作为最细粒度,可以实时反馈代码的质量

代码评审也十分重要,它的主要作用为:

  • 保持代码风格的一致性和可读性,利于贯彻编程规范
  • 提高代码质量,减少Bug
  • 促进互相交流学习,提升团队的整体研发能力,进而提高企业的整体竞争力。

而在测试阶段,我们的主要任务是测试功能性测试类问题,测试阶段的一般流程为:

  • ①撰写测试方案
    由测试人员编写方案并提交开发人员评审。
  • ②进行单元测试
    由开发人员编写用例,并提交测试人员评审。
  • ③进行功能性测试
    由测试人员设计和编写用例
  • ④进行性能/压力等测试
    测试人员根据项目情况决定是否进行
  • ⑤自动化和持续集成
    将测试自动化并并把流程加入持续集成
  • ⑥撰写测试报告
    测试人员要在大版本时撰写测试报告

测试环节涉及很多的内容,包括以下:

  • ①测试方案
  • ②自动化/持续集成
  • ③测试报告

在这一环节中,撰写测试方案是对该阶段工作的整体规划,测试方案描绘了测试和质量保证的各种工作,规划了如何组织测试,方案中包括以下:

  • 质量目标
  • 风险评估
  • 测试范围
  • 测试优先级
  • 测试方案
  • 测试流程
  • 测试计划
  • 测试设计的内容

常用的测试方案,有以下

  • 黑盒/白盒
  • 静态测试/动态测试
  • 自动化测试/手工测试
  • 验收测试/α测试/β测试
  • 单元测试/模块测试/联调测试/系统测试
  • 功能性测试/压力测试/异常测试/安全测试
  • 接口测试/用户场景测试
  • 回归测试
  • 探索性测试

  • 不同的测试方案有不同的特点和擅长解决的问题
  • 测试的侧重点不同,发现的问题也不同
  • 我们需要根据测试方案来选择合适的测试方案,提高测试的效率
  • 为此在前期的测试和设计方案评审时,要及时发现问题,避免无效劳动,提高测试效率。

同样,自动化/持续集成也是有效提高测试效率的方法。

自动化,包括流程自动化和测试自动化。
流程自动化,包含编译、部署、发布、回滚、上线、测试阶段。
测试自动化,可以降低成本并保证测试结果,降低风险。

而基于自动化,我们可以搭建串联工作流,即持续集成。

可以将代码提交->编译->模块测试->部署->系统测试->发布,这一循环性流程集成在一起,从而提高工作效率,保证持续的质量反馈。

测试完成后,需要撰写详细的测试报告,以方便后期的持续维护和迭代。
其内容包括:

  • 测试结果
  • 质量风险评估
  • 质量评估
  • 测试过程描述
  • 缺陷分析
  • 评估改进意见
  • 测试版本/测试人员/测试时间

3 上线与线上阶段的质量保证工作

上线阶段,上线过程和回滚过程.

上线阶段的上线方案,需要经过评审和测试。
对于重点项目,应有回滚方案和相应的评审和测试工作。
上线后,我们需要进行线上测试,常用的线上测试有三类:

  • 众包测试
  • 用户反馈和业务监控
  • 产品测评

1 众包测试
众包测试的目的,是使更多的用户参与测试,降低测试成本。

众所周知,众测服务分为四类:

  • 测试类

    包括:探索性测试、用例组合爆炸测试

  • 产品体验
    包括:产品建议、Badcase收集

  • 评估测试
    包括:包括大数据量评估标注、降低成本

  • 用户调研
    包括:产品需求调研、用户反馈

这里提供一个可供使用的众测平台:http://test.baidu.com

2 用户反馈

用户反馈和业务监控的目的,则是为了实现线上问题闭环,通过用户反馈和业务监控可以解决大部分的线上问题。

步骤分为:

  • 收集
  • 分发
  • 定位
  • 解决

主要平台,有

  • 反馈平台
  • Bugs平台
  • Monitor平台

3 产品评测

产品评测包括,用户反馈分析、产品Bug分析、Top问题分析、竞品对比分析。

  • 用户反馈分析
    是指对用户反馈的问题进行分析
  • 产品Bug分析
    是指对产品的Bug进行分析,然后解决问题最大的Bug
  • Top问题梳理
    是指对问题进行梳理分类,解决最突出的问题
  • 竞品对比分析
    是指对自家产品和市场上同类型产品进行分析

从对各个阶段质量保证工作的分析中,我们不难看出,每一个阶段的质量保证工作都需要多方角色的共同参与。

由此可见,项目的出色质量,来源于每个环节的严格把控和每个成员的共同参与,这是团队质量意识的两大核心。

总结

通过本部分内容的学习,我们总结出质量保证意识的四个核心内容:

  • 1.质量保证工作存在于每一个环节

从需求、设计、开发、测试、上线到上线和线上,每一个环节都有相应的质量保证工作

  • 2.每一个成员都要对质量负责

一个项目中,产品、开发、测试、运营,所有角色对需要对产品的质量负责。

  • 3.测试是一种核心的质量保证工作

    测试可以有效的反馈项目质量,只有测试通过才能说明质量合格。

  • 4.尽早发现问题,尽早解决问题
    患生于所忽,祸起于细微。尽早发现,尽早解决,是减少质量问题带来损失的有效方法。

3.2 代码单元测试总体介绍

代码单元测试总体介绍,主要分为两个部分:

3.2.1 单元测试基础

1 单元测试误区

在正式介绍单元测试之前,我们先一起来了解一下,关于单元测试可能存在的一些认识上的误区:

  • (1)开发单元测试代码的工作量大
  • (2)做单元测试不属于开发人员的职责
  • (3)代码正确率高,进行单元测试必要性不大
  • (4)后期会有集成测试,前期进行单元测试必要性不大
  • (5)单元测试无法带来显著收益,效率不高

2 单元测试的概念

在维基百科中,单元测试的定义为一段代码调用另一段代码,随后检验一些假设的正确性。在百度百科中,单元测试是指对软件的最小可测试单元进行检查和验证。

那么,我们不禁要问,一次编写的单元测试是否只是为了验证该次开发过程中对应的代码逻辑正确性?
其实不然,单元测试不仅在于实现问题中的功能,优秀的单元测试作用长久,可以减少后续工作的负担,从而提升整体生产力。

3 常见的单元测试问题

目前单元测试中存在一些常见的问题:

  • (1)使用System.out输出测试结果,依赖人去判断测试是否正确
  • (2)不使用Assert(断言)对测试结果进行判断

以上两种情形都需要依赖人与电脑的交互,来判断此Case是否成功,在实际的单元测试中,应当使用断言进行判断,使case运行时自动输出结果。

  • (3)没有边界检查
  • (4)多个测试分支放在一个单元测试方法中

这种情况会导致一旦出现运行失败时,难以判断出现错误的分支所在。

  • (5)测试case环境相关(依赖已知库表、时间)
    对于这种情况,应当做出修改,使输入参数为确定的值。

  • (6)测试方法执行有先后顺序
    在实际测试过程中,不同的测试框架对于case执行顺序有自己的行为,故单元测试实际执行顺序存在不确定性。

4 优秀的单元测试

下面来介绍一下优秀的单元测试,需要具备哪些原则:

  • 独立性
    单元测试彼此之间应具有独立性,一个测试应独立于其他测试及运行它的环境。
  • 可重复性
    一个优秀的单元测试是可重复的,它需要具备多次运行的能力,若不可重复,则不能算作优秀的单元测试。
  • 可自动化
    优秀的单元测试可自动化,自动化具备双重含义,第一,单元测试可依赖于现有工具自动化运行;第二,测试执行成功与否可自动进行判断,而不依赖于人为判断,
  • 彻底
    优秀的单元测试是彻底的,单元测试对于被测试对象而言,需要覆盖全部的分支。

3.2.2 单元测试的意义与建议

1 什么情况下做单元测试

(1)单元测试的好处

  • ①带来更高的测试覆盖率
    有些分支问题在集成测试过程中很难发现,但在单元测试中极易发现。
  • ②提高团队效率
    单元测试在开发完后立即执行,将测试提前一步,不必等集成测试时才发现问题。
  • ③自信的重构和改进实现
  • ④将预期的行为文档化

完整的单元测试本身是产品代码的最好文档。

(2)不当的单元测试会降低生产力

单元测试并部署越多越好,不当的单元测试会降低生产力。

  • ①单元测试工作量\普通代码工作量=1:1~1.5:1
    单元测试的工作量与普通代码的工作量的比例介于1:1~1.5:1之间。
  • ②运行时间随着case增多线性增长
    整体项目的单元测试运行时间,随着单元测试case增多,线性增长,测试的执行速度影响多次变更等待的时间。
  • ③单元测试的代码,也需要长期维护

2 不同场景下的单元测试tips

(1)Java Web项目

  • 项目底层的BO\DAO大体都是工具自动生成的,无需额外单测
  • 但是Action(Controller)层不含有较多的业务逻辑,需通过集成测试发现问题
  • 要注意的是,Java Web项目的核心业务逻辑,主要存在于Service层代码中,需要着重进行单元测试。

(2)平台类Java项目

  • 虽然在单独的场景下几乎不会出现问题,但是交叉混合时可能存在问题,且且由于平台类项目,更多的兼顾不同的复杂的应用场景是,所以在测试时要尽量做到全面。
  • 值得注意的是平台类Java项目的分支较多,所以要求在单元测试时,要做到覆盖分支全面。

(3)组件类Java项目和平台类项目

  • 侧重分支覆盖全面,包括异常调用情况的覆盖。

(4)Hadoop的MR任务

Hadoop的MR任务属于特殊的JAVA程序,主要体现在时间成本上。在进行单测时,可以将核心逻辑代码抽取出来,单独测试。

3.3 Python单元测试

Python单元测试,主要分为四个部分:
(1)单元测试的概念、工具与方法
(2)Coverage统计单元测试覆盖率的工具
(3)Mock简化单元测试的工具
(4)总结

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

(1)单元测试的概念

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

(2)单元测试的意义

单元测试的意义,主要包括两个方面:

1 质量

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

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

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

2 效率

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

  • 单元测试进行的时间较早,测试场景构建快,可有效减少调试时间。
  • 由于单元测试只针对修改的代码展开测试,无需考虑额外内容,所以在较短时间内,即可把预期的逻辑测试充分。
  • 单元测试,能够在项目开发初期发现bug,bug发现的时间越早,所带来的收益就越大。由于尽早发现bug能够节省整个项目开发的时间,所以单元测试可加快开发效率,缩短开发周期。

(3)单元测试框架

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

下面介绍三个常用的框架:

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

  • Pytest
    Pytest的好处,在于编码简洁、生态好、插件丰富、使用人数多。

    不足之处在于它属于第三方库,使用前另需提前安装。

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

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

Unittest的基础概念

首先介绍一下,Unittest的几个基础概念。

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

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

  • TestCase测试类
    TestCase可以包含同一个测试对象的多个测试用例,如果一个函数通过三组输入来测试,也就是三个测试用例,这三个测试用例可以合成为一个测试类。

  • TestSuite测试集

    TestSuite可以包含多个测试类的多个测试用例,Assertion断言,必须使用断言判断测试结果。

  • TestFixture
    TestFixture,为测试做统一的准备和清除工作,通常是初始化->连接数据库->准备数据->断开数据库->清除现场等。
    扩展来说,TestFixture有四种最常使用的作用范围,分别为:

    • setUp
      在测试类的每个测试用例执行前执行
    • tearDown
      在测试类的每个测试用例执行后执行
    • setUpClass
      在每个测试类的第一个测试用例执行前执行
    • tearDownClass
      在测试类的最后一个测试用例执行后执行

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

(4)单元测试的规范

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

  • 1 所有的单元测试,必须使用断言assert来判断结果,禁止出现无断言的测试用例。
    使用断言,不但有利于他人理解,而且一旦出现不符合预期的情况,可以立即找出问题,可以使用
    • assertEqualassertNotEqual来判断相等或不相等。
    • assertTrueassertFalse来判断Boolean。
    • assertRaises判断抛出的异常是否符合预期。
  • 2 测试用例需要具有自表述能力,达到见名知意。
    比如命名为test_login_with_invalid_password(),通过它的名字便可知它是用一个非法的密码去测试登录功能,具有自表述能力。
    但是如果命名为test_login_case_(),名字减少了很多信息,难以得知它具体在做什么,就不具有表述能力。
  • 3 测试用例之间相互独立,不应相互依赖、相互调用。
  • 4 一个测试用例只测一个函数
    一个测试用例里面,可以包含这一个函数的多个场景,但不能包含有多个参数的函数,原因在于,复杂测试用例出现错误时,无法定位问题的出处。

(5)单元测试对编码的要求

单元测试中代码需保持一致性,尽量不要出现结果不一致的情况,假设有的代码会带来不一致性,导致单元测试无法稳定运行,针对这种情况,有两种解决方案:

  • 将带来不一致性的代码抽取出来,将其作为一种变量,传入到我们需要调用或使用一致性变量的时候。
  • 借助mock工具来解决这种问题

3.3.2 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=file1[,file 2,...]命令
在统计并打印覆盖率时,排除某些文件,若有多个文件则用逗号分隔;

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

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

3.3.3 Mock简化单元测试的工具

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

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

  • 构造模块
    构造模块,需要测试模块A,但它要调用的模块B还未开发。可是测试缺不容推迟、需按时进行,面对这种情况,我们可以使用Mock生成一个还未写完的代码,即可进行相应的测试。
  • 改变函数逻辑
    代码中含有结果不可预知的代码,例如time.time(0)时间、random.random()随机数。
    Mock可以改变含有结果不可预知代码的函数的逻辑,强行让其返回我们想要的返回值,使其结果可预知。
  • 减少依赖
    在所有模块代码都已完成,但无法保证代码稳定性的情况下,针对其他模块的质量不可靠的情况,可通过Mock工具构造一个相对稳定的模块,从而规避其他模块的问题。

2 Mock使用场景

通过下面10个场景来介绍Mock的常见用法:

  • (1)永远返回我们想要的返回值
    通过return value可以强行修改,永远返回我们想要的返回值。支持的类型包括:string、number、Boolean、list、dict等。

(2)替换类方法的返回值

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

(3)根据调用次数返回想要的结果

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

(4)根据参数返回想要的结果

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

(5)抛出想要的异常或错误

通过side_effect抛出想要的异常或错误

(6)限制mock作用域

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

(7)获取调用信息

如函数是否被调用、函数被调用的次数、函数被调用的形式、函数调用的参数等。

(8)在返回值改变的同时,确保api不会因mock而改变

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

(9)从零构造依赖模块

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

(10)替换函数调用链

替换函数调用链,比如说用popencv去执行一个命令,然后用read函数把它读取出来,再用split去做切分,这就构成了一个函数调用链。

(os.popen(cmd).read().split())

3 Mock对编码的要求

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

3.3.4 总结

下面做一个回顾总结

  • 1 单元测试用Unittest,它是针对函数测试,同时必须用Assert进行结果的判断。

  • 2 若需要判断单元测试的效果,我们需要获得它的覆盖率。
    用Coverage这个工具可以得到覆盖率,其使用方法为用coverage run替换branch,查看覆盖率使用coverage report -m以及coverage report -m -omit=test.py。

  • 3 Mock工具去模拟需要用到的逻辑,Mock可以替换返回值、替换函数逻辑、限制生效范围、获取调用信息等。

3.4 单元测试实践

单元测试实践,主要通过具体的代码案例来讲解介绍。

首先来看,Unittest的简单应用。

3.4.1 Unittest简单应用

如下图所示,这是一个要被测试的类。

这个类代表一个人,类中有一个函数为get_name()。
作用是获取这个人的名字,围绕着这个函数,首先想到的测试点,就是函数能否正确输出人名。

因此,就有了如下图所示的单元测试代码。

  • 第一步,将使用到的unittest框架和所需要的函数导入;
  • 第二步,针对被测试的函数,写一个测试类;
    这里要注意,测试类必须继承自unittest和TestCase
  • 第三步,构建实例化的函数,可以理解为生成两个人,一个叫张三,一个叫李四。
  • 第四步,编写一个用于测试的函数
    这里注意,函数名必须是以test开头

通过图中的代码可以看到,通过使用assertEqual断言来做相应的测试。
断言中包含了两部分,第一部分是预期,第二部分是实际的值。通过对两个值的比较来完成测试。

3.4.2 Unittest复杂应用

下面来看一个复杂的例子。

如下图所示,这个被测试的类是一个公司,这个公司的信息,包含了公司的名字、公司的老板、公司的员工数、在这个公司的类中设置了三个函数:老板是谁、雇佣新员工、解雇一个员工。

通过这些信息,可以想到的测试点有:

  • who_is_boss()
    这个函数能够正确的返回老板的姓名
  • hire()
    使用hire()函数雇佣新人,公司的员工总数+1。
    使用hire()函数重复雇佣一个人,函数会报错,或者公司员工数量不变。
  • fire()
    使用fire()函数解雇一个人,公司的员工总数-1。
    使用fire()函数解雇非公司的员工,函数会报错或者员工总数不变。

针对以上的几个测试点,可以编写出相应的测试类。

首先,需要将所需要的库类导入,并且测试类要继承自unittest和TestCase等。
然后使用setUpClass()函数,构建一个公司,设置老板的姓名和公司的名字,在这里设置了一个tearDown(),清理函数,是为了方便测试的时候将员工全部清理掉,通过图片可以看到,下面三个函数原理基本跟上一个案例相同,都是通过断言来进行测试。

测试类编写完成之后,需要运行这个类进行测试。
如果需要执行全部的测试用例,如图所示,使用unitttest.main()这个函数,且不需要添加任何参数,执行完成后会得到如下图所示的结果,测试结果分为几个部分:

第一部分的代码,展示的是执行测试用例的结果。
“.”说明测试用例执行通过;
“E”说明测试用例发生了特殊情况、异常中断;
“F”说明测试用例执行失败

第二部分,则是打印的报错信息。
出现“E”或者“F”的时候,系统会打印出异常中断和执行失败的原因。

第三部分,为统计信息。
包括了共执行了几个测试用例,测试用例执行共花费了多少时间。
执行用例执行成功或失败的数量等信息。

3.4.3 运行测试集的用例

在真实应用过程中,可能会出现测试用例太多,执行一轮测试用例花费的时间太长,或者,只想执行部分测试用例的情况,在这些情况下,就需要使用测试集进行测试。

下图中是一个测试集函数的代码,它包含以下几个部分:

首先,生成一个测试集;
然后,使用addTest()方法,将测试用例加入测试集中;
最后,编写测试集返回语句,这样就完成了一个测试集的构建。

在执行测试集的时候,使用图中的代码,在unittest_main()中,加入参数,即可完成测试集的运行。

posted @ 2022-06-09 14:33  Xu_Lin  阅读(214)  评论(0编辑  收藏  举报