golang测试 | 青训营

42 阅读3分钟

测试分为三种

  1. 回归测试
  2. 集成测试
  3. 单元测试

从上到下,覆盖率逐层变大,成本却逐层降低

单元测试 规则

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

publish_post.go publish_post_test.go


函数名命名 func TestXxx(*testing.T)

func TestPublishPost(t *testing.T){


初始化逻辑放到 TestMain 中

func TestMain(m *testing.M){
		//测试前:数据装载、配置初始化等前置工作
		code := m.Run()
		//测试后:释放资源等收尾工作
		os.Exit(code)
}

单元测试 运行

func HelloTom() string {
	return "Jerry"
}

func TestHelloTom(t *testing.T) {
	output := HelloTom()
	expectOutput := "Jerry"
	if output != expectOutput {
		t.Errorf("Expected %s do not match actual %s", expectOutput, output)
	}
}
PS E:\Code\go\practice> go test ./A_test.go   
ok      command-line-arguments  0.612s
PS E:\Code\go\practice>

单元测试 assert

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

func HelloTom() string {
	return "Jerry"
}

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

单元测试 依赖

image.png

外部依赖 ⇒ 稳定&幂等

单元测试 文件处理

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

基准测试 运行

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

这两个代码块是 Go 语言中用于性能测试的基准函数(benchmark)。它们都会运行 Select() 函数并返回其运行时间,但第二个函数使用了 b.RunParallel() 函数来并发运行测试循环,相比于第一个函数,第二个函数可以更好地模拟并发负载的情况。

具体来说,BenchmarkSelectParallel() 函数使用了 b.RunParallel() 函数来创建多个 goroutine 并发运行 Select() 函数。每个 goroutine 都会在不同的 CPU 上运行,以便更好地利用多核处理器的性能。这样可以更好地模拟并发负载下的性能表现,从而更全面地评估程序的性能。

与此相反,BenchmarkSelect() 函数没有使用并发,而只是简单地运行 Select() 函数,因此它不能模拟并发负载下的性能表现,并且可能无法完全展现程序在真实场景下的性能表现。

Testing 方法总结

  1. testing.T:是单元测试中最常用的对象,表示一个测试用例。你可以在该对象上调用各种断言方法,如ErrorFailFailNow等来判断测试结果是否正确。
  2. testing.B:是基准测试中使用的对象,表示一个基准测试用例。你可以在该对象上调用ResetTimerStartTimerStopTimer等方法来控制基准测试的计时器。
  3. testing.M:表示一个测试main函数中的对象,主要用于协调测试用例的执行。例如,在测试用例执行之前,你可以在测试main函数中添加一些代码来初始化一些共享资源。
  4. testing.C:表示一个子测试用例,通常是在testing.T对象上调用Run方法时创建的。它允许你对测试用例进行更细粒度的划分和管理。
  5. testing.Short:标记当前测试为短时间测试,用于快速检查某个功能或快速运行测试套件。
  6. testing.Verbose:设置测试输出详细信息,包括每个测试用例的名称以及测试结果等。
  7. testing.PB:是性能测试中使用的对象,表示一个性能测试用例。你可以在该对象上调用StartStop等方法来控制性能测试的计时器。