Golang测试相关问题的求助与讨论
Golang测试相关问题的求助与讨论
我编写了以下简单的代码,以尝试在Go中使用test:
package main
// Init 是输入数字,为了简化,将其作为结构体使用,而不是直接调用函数
type Init struct {
Number int
}
func main() {
d := Init{Number: 3}
d.Double()
println(d.Number, "(which is 3 by 2)")
}
// Double 函数返回输入值乘以2的结果
func (d *Init) Double() {
d.Number = d.Number * 2
}
func ExampleDouble() {
// 为图像创建新的缓冲区
d := Init{Number: 3}
d.Double()
println(d.Number, "(which is 3 by 2)")
// Output:
// 6 (which is 3 by 2)
}
而double_test.go文件的内容是:
package main
import "testing"
func TestDouble(t *testing.T) {
d := Init{Number: 3}
d.Double()
want := 6
if got := d.Number; got != want {
println("test failed")
} else {
println("test passed")
}
}
运行时:
go test -v double_test.go
我得到了以下错误:
# command-line-arguments [command-line-arguments.test]
.\double_test.go:6:7: undefined: Init
FAIL command-line-arguments [build failed]
FAIL
这里有什么问题?测试文件不应该能读取大写的Init类型吗?
更多关于Golang测试相关问题的求助与讨论的实战教程也可以访问 https://www.itying.com/category-94-b0.html
4 回复
你好,
我是一个非常新的初学者,所以如果信息有误请见谅,但如果你像这样运行go命令,只有目标文件会运行,因此现在double.go文件的内容在编译过程中将不可见。尝试不指定目标文件,所以我认为go test -v会起作用。
更多关于Golang测试相关问题的求助与讨论的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
main 包是不可导入的,它也不会自动与同一文件夹中的其他文件合并。请为包使用一个不同于 main 的名称。
avu12:
go test -v
非常感谢,这个方法非常有效,祝你在Go语言的旅程中一切顺利,我也是个新手。
测试文件无法访问Init类型是因为测试文件没有包含被测试的源文件。在Go中,测试文件需要与被测试的代码在同一个包中,并且需要显式包含被测试的文件。以下是解决方案:
问题分析
- 测试文件独立编译:当只运行
go test double_test.go时,编译器只编译测试文件,没有包含main.go文件 - 包级别可见性:
Init类型是导出的(首字母大写),但测试文件找不到它的定义
解决方案
方案1:运行测试时包含所有相关文件
# 运行当前目录下所有测试
go test -v
# 或者明确指定所有文件
go test -v *.go
方案2:修改测试文件,使用正确的测试断言
首先修复 main.go 中的示例测试:
package main
import "fmt"
type Init struct {
Number int
}
func (d *Init) Double() {
d.Number = d.Number * 2
}
func ExampleDouble() {
d := Init{Number: 3}
d.Double()
fmt.Println(d.Number)
// Output: 6
}
然后修复 double_test.go:
package main
import "testing"
func TestDouble(t *testing.T) {
d := Init{Number: 3}
d.Double()
want := 6
if got := d.Number; got != want {
t.Errorf("Double() = %d, want %d", got, want)
}
}
// 表格驱动测试示例
func TestDoubleTableDriven(t *testing.T) {
tests := []struct {
name string
input int
want int
}{
{"positive number", 3, 6},
{"zero", 0, 0},
{"negative number", -5, -10},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
d := Init{Number: tt.input}
d.Double()
if got := d.Number; got != tt.want {
t.Errorf("Double() = %d, want %d", got, tt.want)
}
})
}
}
方案3:使用测试辅助函数(如果需要复杂初始化)
package main
import "testing"
func newInit(n int) *Init {
return &Init{Number: n}
}
func TestDoubleWithHelper(t *testing.T) {
d := newInit(3)
d.Double()
if d.Number != 6 {
t.Fatalf("expected 6, got %d", d.Number)
}
}
运行测试
# 运行所有测试
go test -v
# 运行特定测试
go test -v -run TestDouble
# 查看测试覆盖率
go test -cover
# 生成覆盖率报告
go test -coverprofile=coverage.out
go tool cover -html=coverage.out
关键点
- 测试文件命名:
*_test.go文件需要与被测试文件在同一个包中 - 文件包含:运行测试时需要包含所有必要的
.go文件 - 测试函数签名:测试函数必须以
TestXxx开头,接受*testing.T参数 - 错误报告:使用
t.Error或t.Errorf而不是println来报告测试失败
正确的测试输出应该是:
=== RUN TestDouble
--- PASS: TestDouble (0.00s)
=== RUN TestDoubleTableDriven
=== RUN TestDoubleTableDriven/positive_number
=== RUN TestDoubleTableDriven/zero
=== RUN TestDoubleTableDriven/negative_number
--- PASS: TestDoubleTableDriven (0.00s)
PASS

