Golang测试 | 青训营笔记

61 阅读2分钟

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

本章将从工程实践角度,讲授在企业项目实际开发过程中的所遇的难题,重点讲解Go语言的进阶之路,以及在其依赖管理过程中如何演进。包括:1、语言进阶,从并发编程的视角带大家了解Go高性能的本质;2、依赖管理,了解Go语言依赖管理的演进路线;3、测试,从单元测试实践出发,提升大家的质量意识;4、项目实战,通过项目需求、需求拆解、逻辑设计、代码实现带领大家感受下真正的项目开发。

本节讲述 3、测试,从单元测试实践出发,提升大家的质量意识

测试相关

  • 回归测试
  • 集成测试
  • 单元测试

单元测试

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

example

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)
  }
}

可以通过引入 github.com/stretchr/testify/assert 来简化测试,也有很多开源的assert包

func HelloTom() string {
  return "Jerry"
}
​
func TestHelloTom(t *testing.T) {
  output := HelloTom()
  expectOutput := "Tom"
  assert.Equal(t, expectOutput, output)
}

单元测试 - 覆盖率

func JudgePassLine(score int16) bool {
    if score >= 60 {
        return true
    }
    return false
}
​
func TestJudgePassLine(t *testing.T) {
    isPass := JudgePassLine(70)
    assert.Equal(t, true, isPass)
}

命令行输出

go test judge_test.go judge.go --cover
ok      command-line-arguments  0.420s  coverage: 66.7% of statements

通过添加测试 TestJudgePassLineFail(t *testing.T)

func TestJudgePassLineFail(t *testing.T) {
    isPass := JudgePassLine(50)
    assert.Equal(t, false, isPass)
}

命令行输出

go test judge_test.go judge.go --cover
ok      command-line-arguments  0.326s  coverage: 100.0% of statements

单元测试 - 文件处理

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
}
​
func TestProcessFirstLine(t *testing.T) {
    firstLine := ProcessFirstLine()
    assert.Equal(t, "line00", firstLine)
}

单元测试 - Mock

monkey : github.com/bouk/monkey

快速Mock函数

  • 为一个函数打桩
  • 为一个方法打桩
func TestProcessFirstLineWithMock(t *testing.T) {
    monkey.Patch(ReadFirstLine, func() string {
        return "line110"
    })
    defer monkey.Unpatch(ReadFirstLine)
    line := ProcessFirstLine()
    assert.Equal(t, "line000", line)
}

单元测试 - 基准测试

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()
    }
  })
}

可以尝试 github.com/bytedance/g…

fastrand 在应对高并发的情况下,可能效果更好。

总结

推荐一个github项目 Learn Go With Tests

里面讲了Go的一些基础语法,通过测试的角度出发,感觉有兴趣可以看看。