如何修复 Go 测试输出中的行号?
How to fix line numbers in Go test output?
让我们考虑一下这个简单的测试代码。
(注意:assertSomething
在这里非常简单,但通常我会为手头的任务编写一个更专业的助手,它会查看多个事物并可以报告不止一个错误类型。)
package hello
import "testing"
func TestFoo(t *testing.T) {
assertSomething(t, 2+2 == 4) // line 6
assertSomething(t, 2+3 == 6) // line 7
}
func assertSomething(t *testing.T, expected bool) {
if !expected {
t.Error("Something's not right") // line 12
}
}
当我 运行 go test
时,我得到以下信息:
--- FAIL: TestFoo (0.00s)
hello.go:12: Something's not right
FAIL
exit status 1
FAIL kos/hello 0.008s
我有两个问题:
1) 错误指向第 12 行 - 为什么? t.Error
如何找出它是从哪一行调用的?
2) 在 helper 中,我想指定 t.Error
应该查看更高的堆栈级别以确定要打印的行号,这样我就会收到这样的消息:
--- FAIL: TestFoo (0.00s)
hello.go:7: Something's not right
Python 允许我这样做,例如,在 warnings.warn("message", stacklevel=2)
中 - 我将如何在此处实现等效项?
你可以做你想做的事,你可以通过looking at the source code. The function decorate
了解t.Error
的工作原理,这就是你要找的我想想。
但是,如果您有大量检查代码,并且由于某种原因它在您的测试中重复出现,最好将其提取为 returns 一个错误的函数,而不是传入一个错误testing.T 并使其成为 "assertion"。实际上,FAQ.
语言明确不鼓励编写断言函数。
package hello
import "testing"
func TestFoo(t *testing.T) {
if err := checkSomething(2+2 == 4); err != nil {
t.Errorf("2+2=4 failed: %s", err)
}
if err := checkSomething(2+3 == 6); err != nil {
t.Errorf("2+3=6 failed: %s", err)
}
}
func checkSomething(v bool) error {
if !v {
return errors.New("something's not right")
}
return nil
}
但这是我认为惯用的测试代码的样子。它是 table 驱动的,案例包括输入和预期输出,当测试失败时会导致非常清晰的错误消息。
package hello
import "testing"
func TestFoo(t *testing.T) {
cases := []struct {
a, b, want int
}{
{2, 2, 4},
{2, 3, 6},
}
for _, c := range cases {
if got := operation(c.a, c.b); got != c.want {
t.Errorf("operation(%d, %d) = %d, want %d", c.a, c.b, got, c.want)
}
}
}
func operation(a, b int) int {
return a + b
}
自从 go 1.9 以来,事情有了 changed。
Helper()
方法已添加到 testing.T
和 testing.B
。它旨在从 assertSomething
等测试助手中调用,以指示该函数是一个助手,我们对来自它的行号不感兴趣。
package main
import "testing"
func TestFoo(t *testing.T) {
assertSomething(t, 2+2 == 4) // line 6
assertSomething(t, 2+3 == 6) // line 7
}
func assertSomething(t *testing.T, expected bool) {
if !expected {
t.Helper()
t.Error("Something's not right") // line 12
}
}
输出包含正确的行号:
=== RUN TestFoo
--- FAIL: TestFoo (0.00s)
main.go:7: Something's not right
FAIL
您也可以在 Go Playground try it。
让我们考虑一下这个简单的测试代码。
(注意:assertSomething
在这里非常简单,但通常我会为手头的任务编写一个更专业的助手,它会查看多个事物并可以报告不止一个错误类型。)
package hello
import "testing"
func TestFoo(t *testing.T) {
assertSomething(t, 2+2 == 4) // line 6
assertSomething(t, 2+3 == 6) // line 7
}
func assertSomething(t *testing.T, expected bool) {
if !expected {
t.Error("Something's not right") // line 12
}
}
当我 运行 go test
时,我得到以下信息:
--- FAIL: TestFoo (0.00s)
hello.go:12: Something's not right
FAIL
exit status 1
FAIL kos/hello 0.008s
我有两个问题:
1) 错误指向第 12 行 - 为什么? t.Error
如何找出它是从哪一行调用的?
2) 在 helper 中,我想指定 t.Error
应该查看更高的堆栈级别以确定要打印的行号,这样我就会收到这样的消息:
--- FAIL: TestFoo (0.00s)
hello.go:7: Something's not right
Python 允许我这样做,例如,在 warnings.warn("message", stacklevel=2)
中 - 我将如何在此处实现等效项?
你可以做你想做的事,你可以通过looking at the source code. The function decorate
了解t.Error
的工作原理,这就是你要找的我想想。
但是,如果您有大量检查代码,并且由于某种原因它在您的测试中重复出现,最好将其提取为 returns 一个错误的函数,而不是传入一个错误testing.T 并使其成为 "assertion"。实际上,FAQ.
语言明确不鼓励编写断言函数。package hello
import "testing"
func TestFoo(t *testing.T) {
if err := checkSomething(2+2 == 4); err != nil {
t.Errorf("2+2=4 failed: %s", err)
}
if err := checkSomething(2+3 == 6); err != nil {
t.Errorf("2+3=6 failed: %s", err)
}
}
func checkSomething(v bool) error {
if !v {
return errors.New("something's not right")
}
return nil
}
但这是我认为惯用的测试代码的样子。它是 table 驱动的,案例包括输入和预期输出,当测试失败时会导致非常清晰的错误消息。
package hello
import "testing"
func TestFoo(t *testing.T) {
cases := []struct {
a, b, want int
}{
{2, 2, 4},
{2, 3, 6},
}
for _, c := range cases {
if got := operation(c.a, c.b); got != c.want {
t.Errorf("operation(%d, %d) = %d, want %d", c.a, c.b, got, c.want)
}
}
}
func operation(a, b int) int {
return a + b
}
自从 go 1.9 以来,事情有了 changed。
Helper()
方法已添加到 testing.T
和 testing.B
。它旨在从 assertSomething
等测试助手中调用,以指示该函数是一个助手,我们对来自它的行号不感兴趣。
package main
import "testing"
func TestFoo(t *testing.T) {
assertSomething(t, 2+2 == 4) // line 6
assertSomething(t, 2+3 == 6) // line 7
}
func assertSomething(t *testing.T, expected bool) {
if !expected {
t.Helper()
t.Error("Something's not right") // line 12
}
}
输出包含正确的行号:
=== RUN TestFoo
--- FAIL: TestFoo (0.00s)
main.go:7: Something's not right
FAIL
您也可以在 Go Playground try it。