通过单元测试,我们可以设置多个测试用例,执行要测试的函数,判断是否符合预期。尽可能达保证函数功能没有问题,或者出现我们预知的错误。 将该文件放在与被测试文件相同的包中,该文件将被排除在正常的程序包之外,但在运行 go test 命令时将被包含。 在源码文件中”右键函数名 > Generate… > Test for function“ 便可以快速生成对应函数的单测代码模板,然后我们在生成的模板代码中添加具体的测试用例即可。 ,且报告覆盖率为 100%. 7.使用单测框架写单测 学会使用 Go 官方 testing 包写单元测试是远远不够的,因为实际项目开发中,面对复杂的逻辑判断,繁多的测试用例,网络IO调用等,都加大了单测编写与管理的难度 8.小结 关于单元测试,本文从 0 到 1 讲解了 Go 如何编写测试用例,熟练掌握 Golang 中单元测试的书写是一位合格 gopher 的必备技能。
1、单元测试概述 1.1 什么是单元&单元测试 1.2 为什么进行单元测试 1.3 单元测试用例编写的原则 1.4 单测用例规定 2、golang 常用的单测框架 2.1 testing 2.1.1 1.2 为什么进行单元测试 保证变更/重构的正确性,特别是在一些频繁变动和多人合作开发的项目中 简化调试过程: 可以轻松的让我们知道哪一部分代码出了问题 单测最好的文档:在单测中直接给出具体接口的使用方法 ,是最好的实例代码 1.3 单元测试用例编写的原则 单一原则:一个测试用例只负责一个场景 原子性:结果只有两种情况:Pass、Fail 优先要核心组件和逻辑的测试用例 高频使用库,util,重点覆盖 1.4 单测用例规定 文件名必须要xx_test.go命名 测试方法必须是TestXXX开头 方法中的参数必须是t *testing.T 测试文件和被测试文件必须在一个包中 2、golang 常用的单测框架 结尾的文件,调用测试文件中以 Test或Benchmark开头的函数并给出运行结果 测试函数需要导入testing包,并定义以Test开头的函数,参数为testing.T指针类型,在测试函数中调用函数进行返回值测试
Vite学习指南,基于腾讯云Webify部署项目。
变异测试(Mutation Testing)通过模拟典型应用错误,或者是强制产生有效地测试来定位测试用例设计中的弱点。本文将详细介绍看点信息流Go后台如何提升单测有效性的过程和结果。 解决方法:在Mock函数中使用stmock.Eq()进行输入参数验证。 ? ? 6. 逻辑判断 逻辑判断时存在多种组合,当前测试用例并没有全面覆盖,导致变异体存活。 已覆盖函数,出现大量存活变异体 该函数在其他函数中存在调用,所以在覆盖率统计时被算作已覆盖,但无测试用例来检验该函数。 解决方法:新增单测用例 ? 8. 10.数值计算: 变异体通过变换运算符出现在某一个数值计算中。 解决方法:在测试用例中需要对数值进行确认。 case1: ? 11.条件语句遗漏 变异体检测出条件语句存在遗漏分支。 对变异测试工具、本地运行、平台和流水线搭建、变异体分析、单测用例优化进行了详细的描述。通过尝试变异测试在满足EPC要求的前提下,对自动化用例的有效性进行提升。
腾讯后台开发工程师张力结合了公司级漏洞扫描系统洞犀在DevOps上探索的经验,以Golang为例,列举了编写单元测试需要的工具和方法,然后针对写单测遇到的各种依赖问题,详细介绍了通过Mock的方式解决各种常用依赖 本文结合了公司级漏洞扫描系统洞犀在DevOps上探索的经验,以Golang为例,列举了编写单元测试需要的工具和方法,然后针对写单测遇到的各种依赖问题,提出相应的解决办法,并展示了自动化单元测试的结果。 二、测试工具与方法 1.测试框架 相信大家都熟悉go内置了go test测试框架来执行和管理测试用例。 如下所示,该文件的测试用例都会在m.Run里运行,如果成功返回0否则非零,因此可以判断执行是否成功。值得注意的是最后应该使用code作为os.Exit参数退出。 3.有没有更好折中方案 有时候函数逻辑比较复杂导致插桩过程繁琐,或者有些依赖不方便 mock,那么是否能在执行测试用例的时候创建一个本地测试环境,里面包含了各种依赖,这样或许会方便很多。
我们可以分如下2个阶段:万事开头难,先要会写,先把自动化流水线搞起来,覆盖率报告收集起来,没有写单侧可以通过报表查看到。稳重求进,追求质量和效率,同时关注可测性问题,对测试用例质量进行要求。3. 4.2 等价类划分法等价类划分法假定某一特定的等价类中的所有值对于测试目的来说是等价的,所以在每个等价类中找一个之作为测试用例。 准备测试用例:确保基本路径集中的每一条路径的执行。5. 如何评估单元测试的质量?虽然目前并没有直接的指标去衡量单测的质量,但是我们可以通过一些间接手段保证单元测试的质量。 断言框架由于Golang原生没有提供断言,所以我们需要考虑引入Golang的一些断言组件,下面是几种比较常见的测试框架测试框架推荐指数Go自带的testing包★★☆☆☆GoConvey★★★★★Testify 7.2 goconveygithub地址:https://github.com/smartystreets/goconvey 特性:直接集成go test可以管理和运行测试用例提供了丰富的断言函数支持很多
单元测试用例编写的原则 3.1 理论原则 快。单元测试是回归测试,可以在开发过程的任何时候运行,因此运行速度必须快 一致性。代码没有改变的情况下,每次运行得结果应该保持确定且一致 原子性。 4.2 等价类划分法 等价类划分法假定某一特定的等价类中的所有值对于测试目的来说是等价的,所以在每个等价类中找一个之作为测试用例。 将该文件放在与被测试文件相同的包中。该文件将被排除在正常的程序包之外,但在运行 go test 命令时将被包含。 对于局部数据结构测试,应检查局部数据结构是为了保证临时存储在模块内的数据在程序执行过程中完整性、正确性。局部数据结构往往是错误的根源,应仔细设计测试用例。 Go 单元测试框架是相当易用的,其它的第三方库基本都是建立在 testing 原生框架的基础上进行的增补扩充,在日常开发中,原生包可以满足基本需求,但同样也有缺陷,原生包不提供断言的语法使得代码中的这种片段非常多
前面写了快速上手,会非常快速的创建测试用例,搭建一个单元测试的架子,但是如何来更好的写测试用例呢?我们如何来提升 单测的交互呢 ? 使用goconvey提升单测交互GoConvey是一个非常好用的Go测试框架,它直接与go test集成,提供了很多丰富的断言函数,能够在终端输出可读的彩色测试结果,还支持全自动的Web UI。 ,省略了调用包内函数时的包名前缀,是goconvey推荐的写法。convey函数支持平铺罗列,也支持二层、三层嵌套,用于更细粒度拆分单测用例,一般写两层就够了。 执行go test -v -run Xxx,获取单测结果,可以看到测试用例层级展示,每个So断言对应一个√,出错时可以方便的定位到失败的断言。 这样在 为我们的业务代码:GetStudentTermResult 编写测试用例的时候,就可以直接mock MySQL的操作,测试就非常方便,我们只需要关注 测试业务代码本身是否符合预期就可以了。
23 | 测试的基本规则和流程 (上) 在接下来的日子里,我将带你去学习在 Go 语言编程进阶的道路上,必须掌握的附加知识,比如:Go 程序测试、程序监测,以及 Go 语言标准库中各种常用代码包的正确用法 利用这些 API 和工具,我们可以创建测试源码文件,并为命令源码文件和库源码文件中的程序实体,编写测试用例。 在 Go 语言中,一个测试用例往往会由一个或多个测试函数来代表,不过在大多数情况下,每个测试用例仅用一个测试函数就足够了。 在准备工作顺利完成之后,go test命令就会针对每个被测代码包,依次地进行构建、执行包中符合要求的测试函数,清理临时文件,打印测试结果。这就是通常情况下的主要测试流程。 请注意上述的“依次”二字。 对于每个被测代码包,go test命令会串行地执行测试流程中的每个步骤。
利用go自带框架,最简单的单测代码即可如下: 然后在同目录下输入命令 $go test -v XXX_test.go 其中,-v选项可用于打印每个测试函数的名字和运行时间。 从这个示例中可以看到,testing包提供了Logf和Error等方法来帮助提高测试效率,如果是Error方法的分支被执行了,则这组测试示例会失败,Logf则是在标准输出上输出log信息。 要覆盖被测模块中更多的代码,则需要更多的参数组(测试用例)。实现这个最简单的方法就是多写几个TestXXX,go语言提供了表格驱动的测试方式,把所有测试数据合并到了一个测试中的表格中再集中测试。 go语言中所谓的表格驱动,就是把输入和预期输出做成一个表格,很容易向表格添加新的测试数据,并且后面的测试逻辑也没有冗余,这样我们可以有更多的精力地完善错误信息,比如上例中单元测试是写成类似形式: tests 如果代码中并没有自带http请求,那么测试的时候就需要自己编写代码去构造http请求,。
GO 语言本身没有提供assert 包,不过有很多开源的选择。比如使用https://github.com/stretchr/testify,上面的例子可以简化为: ? 毕竟我们的UT 不仅会跑在自己的开发机上,也会跑在一些沙盒容器里,我们可无法知道这些沙盒容器一定能访问到这个公有云服务。如果访问受限,那么测试用例就会失败。 要让我们的测试用例在任何情况下都能成功运行,写一个 mock 服务会是更好的选择。 这样隔离的原因是所有的测试用例会并发执行,我们不希望我们的用例由于试图在同一时间访问同一个文件而互相影响 。 面向接口编程 这是典型的测试倒逼功能代码。 4、箭头式的代码,提升了圈复杂度,也降低了可测性 5、将内部逻辑与外部请求分开测试(small测试) 6、函数太复杂,没有拆分到位,让单个函数功能行为单一且简单 7、大量使用成员方法和函数,不利于传参进行测试
(xxx可用来识别业务逻辑函数) 单元测试函数参数必须为t *testing.T(测试框架强要求) 测试程序和被测试程序文件在一个包package中 # 示例文件 # 假设我们为某段业务逻辑专门写了一个 : 指定一些测试时的参数(可以指定超时时间,cpu绑定,压测等等(go test包含单元测试,压力测试等)) -test.v: 是否输出全部的单元测试用例(不管成功或者失败),默认没有加上,所以只输出失败的单元测试用例 -test.run pattern: 只跑哪些单元测试用例 -test.bench patten: 只跑那些性能测试用例 -test.benchmem : 是否在性能测试的时候输出内存情况 -test.benchtime 使用xprog参数来运行编译的测试文件(参数类似go run后的参数) i: 安装测试程序中的依赖包,但是不运行测试程序 -json: 以json格式输出测试结果 -o file: 指定测试程序编译后生成的文件名 单元测试中常用的命令参数: # 对当前目录下的全部单元测试程序进行运行测试(也就是所有的xxx_test.go文件中的所有function都会运行) $ go test the rectangular
这里要提一个测试驱动开发,TDD , 现在我们没有采用这种形式,在我们看来,采用TDD开发go项目不是那么顺。 编写测试用例用到的库:testing:golang自带的轻量级测试框架,可以方便快速的写出table-driven的用例,支持go test命令执行单测。 这个文件的所有方法的测试用例,这也是我们没有采用 TDD的开发方式的原因,我们写出大的业务代码框架,之后用gotests来生成测试用例会非常方便,也非常迅速,会大大降低我们因为写测试用例而占用的开发时间 所以没有采用TDD,先写测试用例,之后写业务代码。 /developer/article/1500525总结:坚持在开发过程中写单测是一件困难的事情,它的确会增加我们的开发量。
测试分为4个层次 单元测试:对代码进行测试 集成测试:对一个服务的接口测试 端到端测试(链路测试):从一个链路的入口输入测试用例,验证输出的系统的结果 UI测试 常犯的错误: 没有断言。 没有断言的单测是没有灵魂的。 单测的特征: A:(Automatic,自动化):单元测试应该是全自动执行的,并且非交互式的 I:(Independent,独立性):为了保证单元测试稳定可靠且便于维护,单元测试用例之间决不能互相调用, 通过单元测试,可以在每次构建之后,重新运行整个测试流程,以确保新代码不会破坏已有功能 测试异常场景 一些异常的场景QA不好构造,比如并发出款是否资金安全,事务异常相关测试等等。 除了 mock 变量,gomonkey 还可以直接 mock 导出函数/方法、mock 代码所在包的非导出函数 Go monkey Permission Denied 解决方案:https://github.com
一个测试用例,一般包括以下部分: 稳定的流程 定义测试用例 定义输入数据和期望的输出数据 跑测试用例,拿到实际输出 比较期望输出和实际输出 易变的数据 输入的数据 期望的输出数据 而 table-driven 单测法,就是将流程沉淀为一个可复用的模板、并交由机器自动生成;人类则只需要准备数据部分,将自己的多条不同的数据一行行填充到表里,交给流程模板去构造子测试用例、查表、跑数据、比对结果,写单测这事就大功告成了 子测试用例互相独立:每条数据是表里的一行,被流程模板构造成一个独立的子测试用例。 可调试性强:因为每行数据被构造成子测试用例,可以单独跑、单独调试。 可扩展/可维护性强:改一个子测试用例,就是改表里的一行数据。 接下来,通过举例对比 TestGetWeekDay 的不同单测风格,就能愈发看出 table-driven 的好处。 我们可以借助 Go 官方的 gomock 框架,用其 mockgen 工具生成接口对应的 Mock 类源文件,再在测试用例中,使用 gomock 包结合这些 Mock 类进行打桩测试。
完善测试用例 这里我们开始对示例代码中的函数做单元测试。 = nil) }} 分析代码生成测试用例 对 checkUsername 、 checkEmail 纯逻辑函数编写测试用例,这里以 checkEmail 为例。 ,日常使用中,由于复杂的调用逻辑带来繁杂的单测,也无外乎使用这三个包协同完成。 Q2:执行 -gcflags=all=-l 具体有什么作用 -gcflags 用于在 go 编译构建时进行参数的传递, all 表示覆盖所有在 GOPATH 中的包, -l 表示禁止编译的内联优化。 在 go 中,编译器不会对所有简单函数进行内联优化。go 在决策是否要对函数进行内联时有一个标准:函数体内包含:闭包调用,select ,for ,defer,go 关键字的的函数不会进行内联。
从这一点上讲,每一个测试函数都是是一个能执行的测试用例。) 结果还比较满意,我们运行了这个程序, 不过没有提前退出是因为还没有遇到BUG报告。 当添加了这两个测试用例之后,go test返回了测试失败的信息。 1 FAIL gopl.io/ch11/word1 0.014s 当然,一旦我们已经修复了失败的测试用例,在提交代码更新之前,应该以不带参数的go test命令运行全部的测试用例,以确保修复失败测试的同时没有引入新的问题 通过将测试放到表格中,我们很容易添加新的测试用例。 虽然go test通常在测试完成后就丢弃临时用的测试程序,但是在启用分析的时候会将测试程序保存为foo.test文件,其中foo部分对应待测包的名字。
请在下面的评论中告诉我您的设计和最有意义的地方。 包及其依赖 在开发微服务时,按组件拆分服务很有用。每个组件都应该是独立的,理论上,如果需要,可以将其提取到外部服务。如何理解和实现呢? 包名应尽量简短并能让人一目了然。 每个包都有自己的 Setup()函数。该函数只接收能让该包运行的最基本的参数。 在最开始,这个包包含以下文件: setup.go - 其中包含 Setup()函数, service.go - 它是逻辑文件, repository.go - 它是在读取/保存数据到数据的的文件。 其次,尝试编写更少的测试用例的同时可以覆盖到更多的代码。对于每个主函数的决策/操作,一个成功的测试用例和一个失败的测试用例应该足够覆盖大约 80% 的代码。 有时,程序中有一些关键部分,这部分可以被单独的测试用例覆盖。 最后,在以 _test 为后缀的单独包中编写测试,并将其放入模块中。把所有的东西都放在一个地方是很有用的。
众所周知,在盖房子前,先拉起基准线,再比照着线来砌砖是一个好习惯,而在软件开发中,TDD 就是这个基准线,他要求在开发工作开始前,先根据用户需求编写测试用例,再在开发的过程中不断用测试用例校验代码,直到完全通过即意味着开发完成 缺点 可能造成开发人员将注意力过度集中于单元测试用例,而忽略更加长期的规划 开发过程需要额外维护所有单元测试用例与回归测试用例的正确性,增大开发成本,尤其是在实际工程开发中,需求总是会发生变化,这会造成测试用例的频繁更改 ,更加令人难以维护 GUI、web 页面等难以编写测试用例 3. golang 测试工具 在很多企业中都或多或少的应用着 TDD 的思想,而其本质上是企业对于软件测试的重视,在开发过程中,不断的测试,让问题尽早的暴露和扼杀 现代编程语言中,很多都集成了测试工具,例如 golang 中,就有 testing 包提供一系列测试工具。 通过 go test 命令就可以实现测试用例的执行,通过不同的参数还可以进行例如压测、并发测试等测试功能。 下面就来详细介绍一下。 4. 单元测试 单元测试是最为常见和常用的测试方法。
在平台建压测任务的时候选定一个测试用例为载体,多并发的执行case,统计压测数据,实时展示。以往接口测试和压力测试都是分别写一个方法,里面有很多重复的部分。 期望返回验证:对结果的校验,目前有等于,包含,自定义方法上线文验证等 ) 以用户更新测试用例为例来看一下整个交互流程: 用户浏览器一个case,网页请求后端服务器,Shiro判断登陆状态跳转页面到第三方登陆 压力测试管理 压测场景 支持新建,更新压测场景,压测场景绑定已经建好的接口测试用例,修改用例变量值如用户id来实现多用户压测场景,压测场景包含的信息如下: 压测场景{ 模块:选择压测场景属于的业务模块 用例id:选择压测的case 压测场景:压测的场景的名字 场景说明:该压测的信息说明,如多少个用户,多少并发 压测服务部署机器:部署压测服务的机器IP 启动线程个数:并发线程个数 运行次数:执行多少次case 发送间隔:每个线程每个请求处理完后的休息间隔(可为0) 用例变量:从选择的用例id里带过来的用例变量,便于压测过程中修改方便 压测参数:对用例变量进行取集合值,或从指定数值开始的多少个数,常用于多用户的场景压测
通过上面的方式写完一些用例后,我们把这些用例放到流水线中尝试运行,但很快,我们就遇到了一些问题: 因为一个端到端用例覆盖了多个微服务,用例运行失败后,定位非常困难; 端到端测试在预发布环境运行,我们的预发布环境并没有想像中的稳定 调试运行 2.3.1. go test 直接运行 不管是单测用例,还是接口测试、端到端测试用例,都可以直接用 go test 直接运行。 2.3.2. 链路追踪定位 被测服务接入天机阁后,在接口、集成、端到端测试用例运行中,TestOne 自动化测试工具会将天机阁 Trace ID 打印出来。 经过 review,我们发现了一些问题: 部分用例无断言 有些用例虽然有断言,但断言无实际效果,比如接口测试用例,只断言了返回码,并没有断言实际的返回数据 有些用例虽然写了,但一直没有在流程中运行 有些用例在流程中运行 如下图所示: 使用这种方案后,在关键流程中运行的端到端测试用例,稳定性提升到了 99%以上,让大家对测试信心,有了比较大的提升。 3.1.3.
远程调试(Remote Debugging)提供上千台真实手机,随时随地在真机上进行测试,利用云屏技术对测试方式、操作体验进行了优化,随时截图和记录调试日志,帮助应用、移动游戏快速发现和解决问题,节省百万硬件费用,加速敏捷研发流程。
扫码关注腾讯云开发者
领取腾讯云代金券