Go语言工程实践之测试|zo的笔记|青训营笔记

174 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第1天。 **注:笔记大部分图片内容及代码段为青训营课程

本节主要内容

测试

单元测试 | Mock测试 | 基准测试

本节详细知识点

质量就是“生命”

一些实际开发事故

image.png

测试是避免事故的最后一道屏障

image.png

image.png 回归测试:终端上使用

集成测试:系统功能维度做测试,利用一些接口一些自动化测试

单元测试:测试开发阶段,开发者对单独的函数模块做功能验证 单元测试的覆盖率一定程度上决定着代码的质量

单元测试

单元测试的组成

image.png 输入、测试单元、输出、校对

单元测试-规则

image.png 方便区分源代码与测试代码。以及其相关

image.png 测试函数的命名规范

image.png 单元测试提供一个TestMain函数。在包维度生效。

单元测试-例子

image.png

单元测试-运行

利用go test [flag][packages]指令运行

image.png

单元测试-assert

image.png 有很多开源的assert包可以实现比对的功能

单元测试-覆盖率

image.png 利用代码覆盖率来评估单元测试!

image.png 2/3=66.6%(return false行没有测试到)

image.png

单元测试-Tips

实际项目中覆盖率100%很难

image.png 一般50-60主流程可覆盖。一些资金相关程序尽量60%+

单元测试-依赖

image.png 幂等:重复时结果不变 | 稳定:相互隔离,在任何时间和状况正常运行

需要mock机制实现

单元测试-文件处理例子

image.png 一旦测试文件被篡改了怎么办?

单元测试-Mock

monket是一个开源的mock测试包

image.png

快速mock函数 ————为一个函数打桩(用一个函数A(打桩函数)替换B(原函数))

————为一个方法打桩

image.png target为原函数、replacement打桩的函数 UNpatch()测试结束后卸载桩

mock的实现主要是在go运行时,将内存中函数的地址替换成打桩函数的地址。

对ReadFirstLine打桩测试,不再依赖本地文件: image.png

基准测试

Go语言还提供了基准测试框架

image.png 基准测试指一段程序运行时的性能和cpu的损耗。 其使用方法类似于单元测试

基准测试-例子

服务器负载均衡的例子 image.png 随机选取这10个服务器中的一个

接下来我们测试Select()函数

image.png Benchmark-开头类比于单元测试的Test开头

时间重置为了去掉init的损耗

红框内每次执行cpu的耗时。我们发现并行时有劣化。 因为并行时的rand函数持有全局锁

基准测试-优化

为了解决随机函数的性能问题。需要开源的fastrand函数 ps:fastrand舍弃了一部分随机数列的一致性。但大部分场景不受影响。

image.png

github.com/bytedance/g… (fastrand地址)

小结

单元测试 | mock测试 | 基准测试

项目实践

需求设计 | 代码开发 | 测试运行

需求描述

image.png

需求用例分析

image.png 整个页面是面向用户来消费浏览的。 主要涉及到一个功能点:浏览整个话题页面。 设计两个元素,一个是topic一个是postlist。

思考:Topic和PostLine的属性该有哪些,该如何定义其结构体?

####ER图-Entity Relationship Diagram

image.png Post(帖子)应该带有其附属的topic的编号。

Topic对于post应该是一对多的关系。

分层结构

通用常见分层模型 image.png 数据层数据Model,外部数据的增删改查

逻辑层业务Entiy,处理核心业务逻辑输出

视图层视图View,处理和外部的交互逻辑

组件工具

image.png

github.com/gin-gonic/g…

image.png

go get gopkg.in/gin-gonic/gin.v1@v1.3.0

Repository

如何实现查询操作?

image.png QueryTopicById

image.png QueryPostByParentId

Repository-index

上述两个查询操作如何实现? :因为有文件数据,我们可以通过全扫描遍历的方式。类似于Mysql中的全盘扫描。但这样并不高效。此时

我们需要索引

image.png 将数据行映射成我们数据的map,实现内存的索引 image.png

init一个Topic Index实例: 初始化话题数据索引 image.png

任务:仿照话题索引创建一个回帖索引

实现查询操作

image.png sync.Once在高并发状态只执行一次。单例模式。

Service

service层的函数,主要的目的就是为了pack页面信息

定义一个 页面信息 实体 image.png

service层函数实现的逻辑流程 image.png

代码流程 image.png

checkParam的实现,主要是简单的Id校验 ,实际的开发中严格校验,保护服务端的sever。

prepareInfo的实现。通过repository层的两个查询方法,获取topic以及post的数据。 需要考虑并行来提高执行效率。

image.png

image.png

controller

利用code、msg表示业务的error状态。如: code为o时成功,非0时异常

image.png 代码逻辑:构建view对象->处理业务错误码

端上传来的为string类型,我们要转化为int

Roter

我们的业务逻辑大致完成。接下来通过gin搭建web框架。

流程: 初始化数据索引->初始化引擎配置->构建路由->启动服务

image.png

运行(测试)

go run server.go

image.png 数据就以json格式化的形式展现出来。 |我们一般与端上进行交互,就是暴露给端上这些http的接口。端上拿到json化的response来渲染整个页面。至此整个服务端的实现逻辑就完成车了。

小结

项目拆解 | 代码设计 | 测试运行

实际项目会更复杂,我们可以学会将大需求拆解成小需求来处理问题。