Go语言零到一:覆盖率报告(go 代码覆盖率)

引言

覆盖率报告是一种衡量测试质量的方式,它展示了代码中哪些部分已经被测试覆盖,哪些部分还没有。

1. 生成覆盖率报告

  • 生成覆盖率数据
    • 使用 -coverprofile 选项来生成覆盖率数据文件。
    • 示例:
go test ./... -coverprofile=coverage.out
  • 分析覆盖率数据
    • 使用 go tool cover 命令来分析覆盖率数据。
    • 示例:
go tool cover -html=coverage.out

2. 示例代码

假设我们有一个简单的数学运算包 math,其中包含两个函数 AddSubtract,以及相应的测试。

// math.go 
package math 
 
func Add(x, y int) int { 
    return x + y 
} 
 
func Subtract(x, y int) int { 
    return x - y 
}

3. 测试代码

// math_test.go
package math

import (
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestSubtract(t *testing.T) {
	testCases := []struct {
		x, y, expected int
	}{
		{5, 2, 3},
		{-1, -1, 0},
		{0, 0, 0},
		{2000, 1000, 1000},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%d-%d", tc.x, tc.y), func(t *testing.T) {
			assert.Equal(t, tc.expected, Subtract(tc.x, tc.y))
		})
	}
}

func TestAdd(t *testing.T) {
	testCases := []struct {
		x, y, expected int
	}{
		{2, 3, 5},
		{-1, -1, -2},
		{0, 0, 0},
		{1000, 2000, 3000},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%d+%d", tc.x, tc.y), func(t *testing.T) {
			assert.Equal(t, tc.expected, Add(tc.x, tc.y))
		})
	}
}

4. 生成覆盖率报告

  • 生成覆盖率数据文件
go test ./... -coverprofile=coverage.out
  • 生成 HTML 报告
go tool cover -html=coverage.out
  • 这将生成一个名为 coverage.html 的文件,你可以用浏览器打开查看覆盖率报告。
  • 分析覆盖率报告
  • 覆盖率报告会以 HTML 形式展示代码中的每一行是否被测试覆盖。未覆盖的行将以红色显示,已覆盖的行将以绿色显示。

5. 提高覆盖率

根据覆盖率报告,你可以发现哪些部分没有被测试覆盖,并针对性地添加测试用例。例如,如果你发现某些边界条件没有被覆盖,可以添加相应的测试用例。

// math_test.go
package math

import (
	"fmt"
	"testing"
)

func TestAddEdgeCases(t *testing.T) {
	intMin, intMax := 1, 10
	testCases := []struct {
		x, y, expected int
	}{
		{intMin, 0, intMin},
		{intMax, 0, intMax},
		{intMin, 1, intMin + 1},
		{intMax, -1, intMax - 1},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%d+%d", tc.x, tc.y), func(t *testing.T) {
			result := Add(tc.x, tc.y)
			assert.Equal(t, tc.expected, result)
		})
	}
}

func TestSubtractEdgeCases(t *testing.T) {
	intMin, intMax := 1, 10
	testCases := []struct {
		x, y, expected int
	}{
		{intMin, 0, intMin},
		{intMax, 0, intMax},
		{intMin, 1, intMin - 1},
		{intMax, -1, intMax + 1},
	}

	for _, tc := range testCases {
		t.Run(fmt.Sprintf("%d-%d", tc.x, tc.y), func(t *testing.T) {
			result := Subtract(tc.x, tc.y)
			assert.Equal(t, tc.expected, result)
		})
	}
}

6. 使用覆盖率标签

有时,你可能想跳过某些测试用例的覆盖率统计。你可以使用 //go:cover 注释来标记那些不需要计算覆盖率的代码。

// math.go
package math

//go:cover
func Add(x, y int) int {
	return x + y
}

//go:cover
func Subtract(x, y int) int {
	return x - y
}
原文链接:,转发请注明来源!