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

51 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

首先补充一个上一章的知识点 之前的例子中我们使用time.sleep来保证完成协程的全部执行,那么就存在时间不能够特别精确的问题,那么就存在资源的浪费问题所以引入sync.WaitGroup来减少资源的浪费同时更好的把握协程的执行。

import (
   "fmt"
   "sync"
   "testing"
)

var (
   x    int64
   //用来控制协程的个数
   num  sync.WaitGroup
   lock sync.Mutex
)

func addWithLock() {
   for i := 0; i < 20000; i++ {
      lock.Lock()
      x += 1
      lock.Unlock()
   }
   num.Done()//每完成一个协程-1
}

func addWithoutLock() {
   for i := 0; i < 2000; i++ {
      x += 1
   }
   num.Done()
}

func TestAdd(t *testing.T) {
   x = 0
   //添加协程的个数,需要完成的个数
   num.Add(5)
   for i := 0; i < 5; i++ {
      go addWithLock()
   }
   num.Wait()//只有五个协程都执行完成之后才不会堵塞,程序才能继续往下执行
   fmt.Printf("这是已经加锁的:%v", x)
   x = 0
   num.Add(5)
   for i := 0; i < 5; i++ {
      go addWithoutLock()
   }
   num.Wait()
   fmt.Printf("这是未加锁的:%v", x)
}

4 依赖管理

框架、日志等

GOPATH-->Go Vendor --->Go Module

个人理解:兼容性的一步步增强

依赖管理三要素:

  • 配置文件、描述依赖 go.mod

  • 中心仓库管理依赖库 Proxy

  • 本地工具 go get/mod

image.png

其中indirect表明不是直接依赖

当一个项目中依赖了同一个项目的不同版本,最终编译时所用的版本为最低兼容版本,就是版本号最高的(如果依赖有1.3 1.4 1.5三个版本,然后使用了1.3 1.4,那么编译的时候所用的版本为1.4)

image.png

image.png

5 测试

5.1.1 单元测试-规则
  • 所有测试文件以_test.go 结尾
  • func TestXxx(*testing.T)
  • 初始逻辑放到TestMain中
import (
    "os"
    "testing"
)
func TestMain(m *testing.M) {
    //测试前:数据装载、配置初始化等工作
    //跑这个package下所有的单元测试
    code := m.Run()
    //测试后:释放资源等收尾工作
    os.Exit(code)
}
5.1.2 单元测试-覆盖率

如何衡量代码是否经过了足够的测试?

如何评项目的测试水准?

如何评估项目是否达到了高水准测试等级?

引出代码覆盖率这一概念

`go test 文件名 --cover

5.1.3 单元测试-Tips
  • 一般覆盖率:50%~60%,较高的覆盖率80%+
  • 测试分支相对独立、全面覆盖
  • 测试单元颗粒度足够小,函数单一职责
5.1.4 单元测试-Mock

monkey:github.com/bouk/monkey

快速 Mock 函数

  • 为一个函数打桩
  • 为一个方法打桩

对 ReadFirstLine 打桩测试,不再依赖本地文件

6 基准测试

  • 优化代码,需要对当前代码分析
  • 内置的测试框架提供了基准测试的能力