【青训营】Go的测试

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

Go的测试

测试主要包括回归测试、集成测试、单元测试

一、单元测试

image.png
其中测试单元可以是函数也可以是模块

规则

1.所有测试文件都以_test.go结尾

2.测试函数命名规范:func TestXxx(*Testing.T)

3.初始化逻辑需要放置在TestMain中

以下是一个简单的测试
测试函数HelloTom是否能打印出“tom”如果不行则启动错误打印

import "testing"

func HelloTom() string {
   return "jerry"
}

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

使用以下指令启动测试:

go test 文件名.go

很显然测试不通过实际输出为jerry

image.png

只要将HelloTom的输出改为"tom"就可以通过测试

import (
   "github.com/stretchr/testify/assert"
   "testing"
)

func HelloTom() string {
   return "tom"
}

func TestHelloTom(t *testing.T) {
   output := HelloTom()
   expectOutput := "tom"
   assert.Equal(t, expectOutput, output)
}

上述的代码中使用了来自github的库"github.com/stretchr/testify/assert" ,在判断输出是否相等的时候使用了assert.Equal()函数合理使用第三方库可以减轻我们的开发负担

最终运行结果如下

image.png

以上是单元测试的简单示例

1.2单元测试的评价标准

单元测试的标准主要是代码覆盖率覆盖率越高则证明越多的代码经过了测试。下面我们通过一个例子来了解代码覆盖率。
测试代码覆盖率需要两个文件分别为被测试的代码xxx.go和负责运行测试程序的xxx_test.go
首先是被测试代码Judge.go

// 判断学生成绩是否合格
func JudgePassLine(score int16) bool {
   if score >= 60 {
      return true
   }
   return false
}

接下来是测试程序Judge_test.go

import (
   "github.com/stretchr/testify/assert"
   "testing"
)

func TestJudgePassLineTrue(t *testing.T) {
   isPass := JudgePassLine(70)
   assert.Equal(t, true, isPass)
}

测试代码覆盖率的命令如下:

go test 测试程序 被测试的代码 --cover
示例: go test Judge_test.go Judge.go --cover

输出如下

image.png

输出显示代码覆盖率为66.7%这是因为JudgePassLine一共有三行代码其中score=70的时候只会执行他的if语句和return true语句因此覆盖了66.7%的代码。另外可以提高测试样例数量使得覆盖率为100%

实际项目中达到100%覆盖率是可望不可及的一般项目对于主流层需要覆盖50%而对于资金类的交易等关键操作需要达到80%的覆盖率。对于测试需要有以下要求

  • 测试分支完备独立不重不漏全面覆盖
  • 测试单元粒度足够小函数职责单一

1.3 对依赖的单元测试

image.png
我们在项目中需要依赖一些缓存、数据库或者文件等对其的测试有两个要求

  • 幂等重复运行一个测试其结果是一样的
  • 稳定单元测试是相互隔离的

1.3.1 对文件的处理

对文件的测试主要是用Mock机制
比如有一个函数是用于将文本中所有的11都替换为00但是用传统方法是无法做到反复测试的一旦运行了该函数文本中的11就全部被替换为00了如果再次运行那么实际上这个函数的执行流程实际上是和第一次不一样的而且一旦有人删除了该文件或者修改了该文件也会改变测试结果不满足幂等和稳定的要求

import (
   "bufio"
   "os"
   "strings"
)

func ReadFirstLine() string {
   open, err := os.Open("log")
   defer open.Close()
   if err != nil {
      return ""
   }

   scanner := bufio.NewScanner(open)
   for scanner.Scan() {
      return scanner.Text()
   }
   return ""
}

func ProcessFirstLine() string {
   line := ReadFirstLine()
   destLine := strings.ReplaceAll(line, "11", "00")
   return destLine
}

此时我们就需要使用到Mock函数进行打桩。我们使用到的比较常用的Mock包是Monkey其代码仓库地址是https://github.com/bouk/monkey 。其中打桩可以使用函数A去替换需要被测试的函数B。其中Patch为打桩函数Unpatch为卸桩函数。

image.png

施工中🚧待完善

二 基准测试

import (
   "math/rand"
   "testing"
)

var ServerIndex [10]int

func InitServerIndex() {
   for i := 0; i < 10; i++ {
      ServerIndex[i] = i + 100
   }
}

func Select() int {
   return ServerIndex[rand.Intn(10)]
}

func BenchmarkSelect(b *testing.B) {
   InitServerIndex()
   b.ResetTimer()
   for i := 0; i < b.N; i++ {
      Select()
   }
}

func BenchmarkSelectParallel(b *testing.B) {
   InitServerIndex()
   b.ResetTimer()
   b.RunParallel(func(pb *testing.PB) {
      for pb.Next() {
         Select()
      }
   })
}
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go