程序员的测试课

article/2025/10/16 3:27:18

git项目地址:GitHub - dreamhead/geektime-todo: Geektime Todo is a demo todo project for Geektime column.

1、实现一个Todo应用

设计规范
1、对于输入参数的检测,由入口部分代码进行处理。如空字符串。
2、Repository 的问题以运行时异常 的形式抛出,业务层不需要做任何处理 如存储到Repository的时候出现问题如存储到磁盘但磁盘满了

先写单元测试代码,再写代码。

2、实现一个todo的应用下


 

 测试覆盖率给了我们发现代码问题的机会。
在构建脚本设定的测试覆盖率是 100%,所 以,只要有测试覆盖不到的地方就会被发现。

3、程序员的测试与测试人员的测试有什么不同?

有意识地在写代码的时候编写测试,尽自己所能把各种场景考虑到。
只要团队里有合格的测试人员,他总会以你想不到的角度,发现系统中意想不到的问题
程序员的出发点是实现,而测试人员的出发点是业务。
目前大多数团队的情况是,测试人员并没有得到充分的发挥。只有程序员做好了自己的测
试,测试人员才能从日常琐碎的验证工作中解脱出来,去做更有价值的测试
如果程序员能够把自己的测试做好,很多问题就应 该被消灭在萌芽状态,根本不应该到测试同学这里。


向测试学习


1、业务视角,
但无论是什么样的测试工具,都只是提升效率的一种手段。如果没有背后的测试思维支撑,再好的工具,也是没用的。
2、学会设计测试,找到更多的测试场景。
程序员每多想到一点,软件质量就能多提高一点
测试人员设计好用例后共享,让程序员能够又一个参考去编写自己的测试。(很少有写单元测试的开发)
测试从测试场景入手,多考虑各种情况,尤其是异常情况。

4、自动化测试:为什么程序员做测试其实是有优势的?

程序员在测试上的优势所在,也就是自动化
理解自动化测试框架,主要包含两个部分:组织测试的结构以及断言。组织测试的结构最
核心的就是测试用例如何写,以及 setUp 和 tearDown 函数。而断言则是保证了我们测试
的目标。断言程序库有很多,你可以根据自己的喜好进行选择。除了断言程序库,Mock
框架的 verify 也是一种断言。


如果今天的内容你只能记住一件事,那请记住:没有断言的测试不是好测试。

05 | 一个好的自动化测试长什么样?

1、把测试写简单,简单,到一目了然,不需要证明它的正确性。


2、一个自动化测试用例,的结构分别是准备、执行、断言和清理。其中,核心的部分是执行和断
言。一个测试既不能执行太多的东西,也不能没有断言。


3、如何衡量一个测试有没有做好?-A-TRIP标准
Automatic,自动化;--需要有断言
Thorough,全面的;-测试覆盖各种场景
Repeatable,可重复的; 能够反复执行,并且结果都是一样


影响一个测试可重复性的主要因素是外部资源,
常见的外部资源包括文件、数据库、中间件、第三方服务等等。如果在测试中遇到这些外
部资源,我们就要想办法让这些资源在测试结束后,恢复原来的样子。


Independent,独立的; 测试和测试之间不应该有任何依赖。
Professional,专业的 按照代码的标准去维护。这就意味着你的测试代码也要写得清晰,比如良好的命名、把函数写小、要重构甚至要抽象出测试的基础库、测试的模式


测试用例命名:
should_ 测试场景;
should_ 测试效果 _while_ 测试条件。
 

 06 | 测试不好做,为什么会和设计有关系?

测试不好做,实际是可测试性不好,原因是代码没设计好。
如何编写可测试的代码,最简单的回答就是让自己的代码符合软件设计原则。
编写可测试的代码,如果只记住一个通用规则,那就是编写可组合的代码。

07 | Mock 框架:怎么让测试变得可控?

Mock 框架的基本逻辑很简单,创建一个模拟对象并设置它的行为,主要就是用什么样的
参数调用时,给出怎样的反馈。


08 | 单元测试应该怎么写?

如何去写单元测试。很多团队由于多方面的原因(比如设计做得不好),导 致单元测试写得少。但为了提高代码质量以及更准确地定位问题,我们应该多写单元测 试。

单元测试最好是和实现代码一起写,以便减少后续补测试的痛苦。想写好测试,关键要做 好任务分解,否则,面对一个巨大的需求,没有人知道如何去给它写单元测试。

编写单元测试的过程,实际上就是一个任务开发的过程。一个任务代码的完成,不仅仅是 写了实现代码,还要通过相应的测试。一般而言,任务开发要先设计相应的接口,确定其 行为,然后根据这个接口设计相应的测试用例,最后,把这些用例实例化成一个个具体的 单元测试。

单元测试常见的一个问题是代码一重构,单元测试就崩溃。这很大程度上是由于测试对实 现细节的依赖过于紧密。一般来说,单元测试最好是面向接口行为来设计,因为这是一个 更宽泛的要求。其实,在测试中的很多细节也可以考虑设置得宽泛一些,比如模拟对象的 设置、模拟服务器的设置等等。

如果今天的内容你只能记住一件事,那请记住:做好任务分解,写好单元测试。

09 | 测试覆盖率:如何找出没有测试到的代码?

测试覆盖率是一种度量指标,指的是在运行一个测试集合时,代码被执行的比例
常见的测试覆盖率指标
有下面这几种:

函数覆盖率(Function coverage):代码中定义的函数有多少得到了调用;
语句覆盖率(Statement coverage):代码中有多少语句得到了执行;
分支覆盖率(Branches coverage):控制结构中的分支有多少得到了执行(比如 if 语
句中的条件);
条件覆盖率(Condition coverage):每个布尔表达式的子表达式是否都检查过 true
和 false 的不同情况;
行覆盖率(Line coverage):代码中有多少行得到了测试


JaCoCo:一个 Java 的测试覆盖率工具

JaCoCo 是 Java 社区常用的一个测试覆盖率工具JaCoCo 是 Java 社区常用的一个测试覆盖率工具
把测试覆盖率与提交过程联系起来。我们在实战中,提交之前要运行检查过程。

         测试覆盖率是帮我们发现在测试中没有覆盖到的代码,也就是帮助我们在测试之外查缺补漏。
        测试覆盖率实际上是一组不同指标的组合,所谓覆盖率就是运行一组测试,执行到的元素
和总的元素比例。大部分指标都比较好理解,只是条件覆盖率要求比较高,与其通过测试
覆盖那么多的条件,不如把代码本身写简单,降低测试的难度。
     我以 JaCoCo 为例,给你介绍了一个测试覆盖率工具,其中的 counter 对应着测试覆盖率
的指标。在实际的项目中使用测试覆盖率工具,关键是要把它与自动化的过程结合起来,
让它不是独立的存在。每次提交,每次 CI 过程都要进行测试覆盖率的检查。
     最后我们还讲到了如何通过测试覆盖率的报告找到未覆盖的代码,定位到问题之后,补齐
测试对于大多数程序员来说还是相对容易的。
       如果今天的内容你只能记住一件事,那请记住:将测试覆盖率的检查加入到自动化过程之
中。

10 | 为什么 100% 的测试覆盖率是可以做到的?

要尽可能地把自己的工作数字化

要想写好测试,一个关键点是要有良好的软件设计,而且代码
本身要尽可能地消除坏味道。

我们强调的 100% 测试覆盖,主要指的是对自己编写的代码 100% 测试覆盖。这就意味
着,我们一方面要保证自己的代码完全可控,另一方面,对于影响到测试覆盖的第三方代
码要进行隔离。

要想做到 100% 的测试覆盖,技术上说,要有可测试的设计以及编写整洁
的代码,实践上看,要测试和代码同步产出。

100% 的测试覆盖并不是说代码没有问题了,而应该是程序员对自己编写代码的一种质量
保证,它是一个帮助我们查缺补漏的过程。
对于无法测试到第三方代码,要用一个薄薄的隔离层将代码隔离出去,在构建脚本中将隔
离层排除在外。有一点需要注意的是,排除脚本千万别被滥用了。

如果今天的内容你只能记住一件事,那请记住:100% 的测试覆盖率是程序员编写高质量
代码的保证。

TDD写出来的代码一般情况覆盖率都是100%

11 | 集成测试:单元测试可以解决所有问题吗?

今天我们讲了集成测试,相对于单元测试只关注单元行为,集成测试关注的多个组件协同 工作的表现。今天我们讨论了两类典型的集成问题,一种是代码之间的集成,一种是代码 与外部组件的集成。 对代码之间的集成来说,一方面要考虑我们自己编写的各个单元如何协作;另一方面,在 使用各种框架的情况下,要考虑与框架的集成。如果我们有了单元测试,这种集成主要是 关心链路的通畅,所以一般来说我们只要沿着一条执行路径,把相关的代码组装到一起进 行测试就可以了

如果涉及框架,最好是能够把框架集成一起做了,设计得比较好的框架是对于测试的支持 比较好的(比如像 Spring Boot),可以让我们很方便地进行测试。 对于外部组件的集成而言,难点在于如何控制外部组件的状态。数据库在这方面相对已经 有比较成熟的解决方案:使用单独的数据库,以及在测试结束之后进行回滚。 但大部分系统没有这么好的解决方案,尤其是第三方的服务。这时候,我们就要看有没有 合适的替代方案。对于大多数 REST API,我们可以采用模拟服务器对服务进行模拟。 通过今天的讨论你会发现,严格地说,有些代码由于基础设施的问题是不容易在自动化场 景覆盖的,这也是我们为什么要强调与框架结合的代码一定要薄,让这种代码的影响尽可 能少。这也是在减少用上层测试覆盖的工作量。

到这里,大部分的场景我们都已经可以用自动化测试进行覆盖了,我们对自己的系统已经 有了更完整的理解。其实,测试的种类还有更多,比如系统测试,把整个系统集成起来测 试;验收测试,交由业务人员或测试人员进行测试。但这些测试对于很多团队来说,已经 到了测试人员的工作范畴了。作为程序员,我们能够把单元测试和集成测试做好,整个软 件的质量已经是初步合格了。

如果今天的内容你只能记住一件事,那请记住:想办法将不同组件集成起来进行测试。

12 | 实战:将 ToDo 应用扩展为一个 REST 服务

集成测试回滚数据,保证测试的可重复 性。

13 | 在 Spring 项目中如何进行单元测试?

15 | 测试应该怎么配比?

冰淇淋模型

金字塔模型

 

 

 从实用的角度上看,我们不 太可能用各种类型的测试做所有代码的覆盖,这是一种浪费。 在决定如何配比各种类型的测试前,你首先要了解各种测试的特点。比如,单元测试速度 快成本低,但覆盖面小;集成测试和系统测试覆盖面大,但速度慢成本高。

行业中目前有两种典型的测试模型:冰淇淋蛋卷和测试金字塔。二者对于测试的配比要求 刚好相反,冰淇淋蛋卷要求多写高层测试,而测试金字塔则希望多写低层测试。 行业中的最佳实践是测试金字塔,这是每个新项目都应该做到的。

对于遗留项目,我们可 以在一开始的时候,先采用冰淇淋蛋卷建立基础的安全网,在有了最低保障之后,开始向测试金字塔方向努力。 如果今天的内容你只能记住一件事,那请记住:新项目采用测试金字塔,遗留项目从冰淇 淋蛋卷出发。

16 | 怎么在遗留系统上写测试?

今天我们谈到了在遗留系统上写测试。遗留系统就是那些没有测试的系统,给遗留系统写 测试就是让一个系统恢复正常的过程。 在遗留系统上做改进,关键是要知道改进成什么样子。在一个遗留系统上写测试,不仅是 写测试,还会牵扯到写代码。 完整地给一个遗留系统写测试是比较困难的。一个实用的改进策略是,动到哪里,改哪 里。具体如何写测试,最好是测试的层次越低越好,但低层次的测试就会涉及代码耦合的 问题,而这里就需要我们对代码进行解耦。 解耦,主要是把业务代码和具体实现分开。通过提取方法,把一段耦合紧密的代码隔离 开,再创建一个新的封装类把它挪进去。如果代码里有很多具体类,我们还可以通过引入 接口进行解耦。这里面的关键是利用 IDE 给我们提供的重构功能,减少手工改代码的操 作。 如果今天的内容你只能记住一件事,那请记住:改造遗留系统的关键是解耦。

17 | TDD 就是先写测试后写代码吗?

TDD 的一个关键要素,TDD 的节奏:红 - 绿 - 重构

 测试先行开发和测试驱动开发的差异就在重构上。

重构就是一个消除代码坏味道的过程。

测试驱动开发要从任务分解 开始。

为了写测试,首先“驱动”着我们把需求分解成一个一个的任务,然 后会“驱动”着我们给出一个可测试的设计,而在具体的写代码阶段,又会“驱动”着我 们不断改进写出来的代码。把这些内容结合起来看,我们真的是在用测试“驱动”着开 发。

无论你是否采用 TDD 的实践,在动手写代码之前,从测试的角度进行思考都是非常有价值 的一件事,这也是编写高质量代码的重要一环。 如果今天的内容你只能记住一件事,那请记住:从测试的视角出发看待代码。

18 | BDD 是什么东西?

今天最流行的 BDD 框架应该是 Cucumber

BDD,也就是行为驱动开发。这种思想是站在 xUnit 的框架基础之上, 让测试用例的表达更贴近业务行为。

BDD示例

核心点就是它的描述格 式:“Given…When…Then”。Given 表示一个假设前提,When 表示具体的操作, Then 则对应着这个用例要验证的结果。

BDD是站在业务的角度

想 写好 BDD 的测试用例,关键点在用业务视角描述。 

了 BDD 的延伸,无论是 BDD 风格的单元测试框架,还是活文档、实例 化需求,这些都是你可以进一步探索的东西。 如果今天的内容你只能记住一件事,那请记住:技术团队要更加贴近业务。

总结

软件质量的病不在外部,而在内部。一个没有质量意识的团队只靠外部的推动很难做出高 质量软件

软件质量要想得到真正的提升,要将做到 内建质量(Build Quality In)。

内建质量,就是将质量的思考内建于软件开发的全生命周期中。

内建质量就是要把软件开发中的每一个环节都加入 质量的考虑:

业务负责人不能只要求上线日期,也要给出需求验证的业务目标和业务的验收标准; 产品经理不只是要给出产品说明,更要给出每个需求点的验收标准; 程序员不只给出代码,还要给出覆盖每行代码的自动化测试。

所谓内建质量,本质上就是用任务分解的方式,让每个环节都交付满足一定质量标准的交 付物

写代码时问问自己,这段代码应该怎么测


http://chatgpt.dhexx.cn/article/mrohRauQ.shtml

相关文章

软件测试重点知识

软件测试的定义: 利用人工或自动化的手段来运行或测定某个系统,其目的在于测它是否满足规定的需求或检测预期结果与实际结果之间的差异。 软件测试的目的: 发现软件中存在的问题或缺陷,检查软件系统是否满足要求。 软件测试的对象…

跑批利器--读取文件

在上篇文章中已经对示例的基本业务和流程进行了解,同时也知道了SpringBatch的三个接口ItemReader,ItemProcessor,ItemWriter.接下来我们主要是通过示例来具体处理一个文本文件,将里面的数据和内容通过SpringBatch的加工处理来存到新的数据库中. SpringBatch提供专门的类去读取文…

金融任务实例实时、离线跑批,Apache DolphinScheduler 在新网银行的三大应用场景与五大优化...

在新网银行,每天都有大量的任务实例产生,其中实时任务占据多数。为了更好地处理任务实例,新网银行在综合考虑之后,选择使用 Apache DolphinScheduler 来完成这项挑战。如今,新网银行多个项目已经完成了实时与准实时的跑…

线程并发处理跑批任务

定时任务类代码: package com.jzfq.rms.autoApprove.job;import com.alibaba.fastjson.JSONObject; import com.jzfq.rms.autoApprove.bean.InnerRuleProcess; import com.jzfq.rms.autoApprove.bean.InnerRuleProcessQueryBean; import com.jzfq.rms.autoApprove.s…

Oracle-job跑批变慢案例

前言: 近期处理了一起应用job跑批变慢的案例,在一天job执行时间突然增加了几十倍,后面通过分析是由于索引的设计不合理导致执行计划的异常,把当时的问题分析过程记录下来,分享给大家。 问题: 数据库job存储执行时间增加几十倍 原因…

架构师自诉:如何做到百万数据半小时跑批结束

业务背景 跑批通常指代的是我们应用程序针对某一批数据进行特定的处理 在金融业务中一般跑批的场景有分户日结、账务计提、欠款批扣、不良资产处理等等 具体举一个例子 🌰 客户在我司进行借款,并约定每月 10 号码还款,在客户自主授权银行…

基于Kettle跑批的案例说明

需求概述 通过动态配置表的方式完成在kettle里动态配置参数,并调用ktr,实现跑批的目的。 问题分析 定义一个ktr读取配置表的信息并将拷贝记录到结果定义一个ktr从结果里获取记录并设置变量定义业务ktr(即按照业务需要开发的…

学习笔记-如何设计离线跑批系统

一、基本概念 离线跑批:通常指批量加工数据、完成一系列流程的定时任务。 业务场景:在银行、金融、支付出现较多,其他行业也可能涉及。 1. 定时的数据状态更新(到期失效) 2. 数据计算(计算罚息、计提&…

跑批利器--示例

接下来我们将通过简单的一个在线商店的应用示例来展示如何使用SpringBatch.通过这个示例我们可以进一步去理解SpringBatch批量处理程序它是如何实现高效的读写数据,何时去使用内部组件,如何实现你自己的组件,以及如何配置一个批量任务在Spring容器中. 这里我们简单描述一下业务…

如何设计一个多线程处理跑批功能

一、背景 最近承接了一个需求,背景是用户当天可以参与比赛竞猜,当天20点前参与竞猜,第二天上午10点出结果。系统的实现思路是用户参与竞猜时增加竞猜记录,第二天早上9点开始进行跑批,跑批依赖业务的配置,要…

跑批利器--批处理应用程序

目前笔者正在进行直销银行互联网核心的设计和研发,在银行相关系统中有一块内容比较关键,那就是跑批.因此接触到了SpringBatch的相关内容,作为学习和记录,有必要将SpringBatch的相关技术点和实际项目中遇到的问题记录下来,同时也跟各位来进行分享和学习. 首先先了解一下什么是批…

跑批 流程、代码梳理

权限系统 全部——ETL服务——计划维护 日程表:到时间触发跑批任务 复制任务编号 ETL设计——作业设计——自定义java——插入语句 找到类所在位置 org.isscloud.portal.agent.scf.batch.FinaResultBatch base下的agent下的scf.batch包下的FinaResultBatch类 S…

跑批为什么这么难

文章目录 问题分析SPL用于跑批应用效果SPL资料 业务系统产生的明细数据通常要经过加工处理,按照一定逻辑计算成需要的结果,用以支持企业的经营活动。这类数据加工任务一般会有很多个,需要批量完成计算,在银行和保险行业常常被称为…

Java开源专业计算引擎:跑批真的这么难吗?

业务系统产生的明细数据通常要经过加工处理,按照一定逻辑计算成需要的结果,用以支持企业的经营活动。这类数据加工任务一般会有很多个,需要批量完成计算,在银行和保险行业常常被称为跑批,其它像石油、电力等行业也经常…

银行跑批业务 的 初步理解(批量批量.....流水账)

一、初步理解 白天的柜台交易, 实时的 对帐户进行操作。 晚上 批量 , 比如 一些报表的生成 , 定期储蓄到期的自动转存 , 行内行外业务清分清算 , 有时还可能赶上利息计算....... 当然 不是所有的数据都是实时操作 , 因此跑批就是为此诞生。 二、逐渐深入 批量…

跑批设计-如何才能让跑批更加高速

跑批的应用场景 在开发过程中跑批经常使用的地方: 消息类:到期失效以及到期批量通知客户计算类:在财务中的罚息、计提、计息文件类:对账信息、还款信息同步以及报表生成 跑批数据特点 数据量非常大实时性并不是特别高&#xf…

跑批bat、shell

“跑批”也叫“批量处理”。批处理,也称为批处理脚本。顾名思义,批处理就是对某对象进行批量的处理,通常被认为是一种简化的脚本语言,它应用于DOS和Windows系统中。批处理文件的扩展名为bat 。 批处理定义:顾名思义&a…

gPRC基础教程

1.什么是RPC? RPC 远过程调用.在理解远程调用之前,首先我们来了解一下本地调用,只有更好的理解了本地调用,才能更好的理解RPC. 1.1 本地调用ex:本地的函数调用在函数调用的时候,一般会经过几个步骤 返回地址入栈参数入栈提升堆栈空间函数参数的复制执行函数调用清空堆栈 1.…

GPRM/GNRMC定位信息的读取与解析

GPRM/GNRMC定位信息的读取与解析 参考网址:http://www.cnblogs.com/88223100/p/GPRM_GNRMC_Transform.html 帧头 UTC时间 状态 纬度 北纬/南纬 经度 东经/西经 速度 $GPRMC hhmmss.sss A/V ddmm.mmmm N/S dddmm.mmmm E/W 节 方位角 UTC日期 磁偏角…

GPRMC转经纬度 地理位置

前言 一、GPRMC是什么? 二、GPRMC如何转经纬度 三、python加地图实现定位 1.Python代码 2.地图定位 四、通过python直接输出位置的尝试 1.需要用到的库geocoder 2.需要准备的库folium 总结 前言 在实际汽车路测的时候会出现GPS偏移,这个时候就需要将GPR…