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

104 阅读4分钟

03测试

  • 测试是应用发布上线前的最后一步,覆盖率高的测试可以保证上线的应用的可靠性、稳定性和安全性,是避免事故的最后一道屏障。
  • 测试主要分为三种:
    • 回归测试:QA人工测试
    • 集成测试:对系统功能进行测试
    • 单元测试:开发者对单独的模块进行测试。 -> 保证质量、提升效率

在这里插入图片描述

3.1 单元测试

3.1.1 规则

  • 所有测试文件以** _test.go** 结尾
  • 测试函数命名规范为:func TestXxx(t *testing.T) {}
  • 初始化逻辑放在 TestMain 中:
func TestMain(m *testing.M) {
    //测试前:数据装载、配置初始化等前置工作
    
    code := m.Run()
    
    //测试后:释放资源等收尾工作
    
    os.Exit(code)
}

3.1.2 例子

  • 接下来以一个返回字符串的函数的测试为例,展示测试函数的使用:
    • 被测试函数:
func HelloTom() string {
    return "Jerry"
}

这个函数的本意是返回 “Tom” 字符串,但是却返回了 “Jerry”。 测试代码:

func TestHelloTom(t *testing.T) {
    output := HelloTom()
    expectOutput := "Tom"
    if output != expectOutput {
        t.Errorf("Expected %s do not match actual %s", expectOutput, output)
    }
}

在测试函数中检测出了问题。

3.1.3 覆盖率

  • 代码覆盖率,是一种通过计算测试过程中被执行的源代码全部源代码的比例,进而间接度量软件质量的方法。它在保证测试质量的时候潜在保证实际产品的质量,可以基于此在程序中寻找没有被测试用例测试过的地方,进一步创建新的测试用例来增加覆盖率。
  • 在实际项目中,一般覆盖率在 50%~60% 之间,较高覆盖率能达到 80%+。

可以通过下面的方法尽可能地提高覆盖率:

  1. 测试分支相互独立,全面覆盖。
  2. 测试单元粒度足够小,函数单一职责。

3.2 单元测试-依赖

  • 单元测试要求幂等&稳定

    • 幂等:重复运行测试一个 case 时,其结果应保持相同。
    • 稳定:单元测试之间是相互隔离的。

3.3 单元测试-Mock

Mock 意为 “模仿的;模拟的”,是指在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的 Mock 对象来创建以便测试的测试方法。

3.4 基准测试

  • 用于优化代码,对当前代码进行分析。-> 内置的测试框架提供了基准测试的能力。

04 项目实践

以掘金社区话题页面为例,讲述项目开发的流程: 在这里插入图片描述

4.1 需求描述

展示话题(标题,文字描述)和回帖列表; 暂不考虑前端页面实现,仅仅实现一个本地 web 服务; 话题和回帖数据用文件存储。

4.2 需求用例

用 UML 来形象直观地表示需求。在这个项目中,UML 图展示如下: 在这里插入图片描述

4.3 ER图

  • ER:Entity Relationship,实体关系。 ER 图表征了现实世界的概念模型及它们之间的关系。在这个项目中,ER 图展示如下:

Topic 和 Post 是一对多的关系。

4.4 分层结构

主要采用分层结构来进行项目代码的设计,这样做逻辑清晰,职责明确,通过各层之间暴露的接口来进行合作,而不需要知道其他层的代码实现细节,有利于提高代码编写的效率。

  • 分层结构主要分为以下几层:
    • 数据层:数据 Model,外部数据的增删改查;
    • 逻辑层:业务 Entity,处理核心业务逻辑输出;
    • 视图层:视图 view,处理和外部的交互逻辑。

4.5 组件工具

  • 我们在搭建社区话题页面时,并不需要从零开始一步步搭建,而可以站在巨人的肩膀上,在他人开源的框架的基础之上进行业务开发。 这是一个开源的 Gin 高性能 go web 框架:gin-gonic/gin: Gin is a HTTP web framework written in Go (Golang).

4.6 项目搭建流程

  1. 在项目构建之初,我们用 go mod init 进行初始化,然后通过 go get gopkg.in/gin-gonic/gin.v1@v1.3.0 来远程拉取代码包及其依赖包,并自动完成编译和安装。

  2. 根据之前的需求分析对数据层 Repository 的数据库部分进行代码编写,应该实现两个基本的查询操作:

  • 根据话题 Id 查询话题:QueryTopicById
  • 根据话题 Id 查询所有帖子数据:QueryPostByParentId
  1. 在数据库中查询到数据后,将其传输到逻辑层 Service 进行处理:参数校验 checkParam -> 准备数据 prepareInfo -> 组装实体 packPageInfo ;

  2. 然后在视图层 Controller 将从逻辑层得到的数据显示为话题页面。

  3. 最后,利用 gin 这个框架来完成整个项目的实现。包括:

  4. 初始化数据索引

  5. 初始化引擎配置

  6. 构建路由

  7. 启动服务