当一个测试恐慌时,任何延迟执行的函数仍然会处理,允许测试正确清理。如果延迟执行的函数执行了 t.FailNow()
,测试输出将不包括关于恐慌或恐慌的 goroutine 跟踪的信息。
下面是一个示例:https://play.golang.org/p/gWPDVluKaST
尽管测试明显在延迟执行的函数中恐慌(使用 t.FailNow()
),但测试输出仅显示:
--- FAIL: TestPanic (0.00s)
FAIL
期望的行为应该是类似于这个示例:https://play.golang.org/p/qrLtmYnkqAh (其中延迟执行的函数调用 runtime.Goexit()
)这会产生以下输出:
--- FAIL: TestPanic (0.00s)
panic: Test Panic
panic: test executed panic(nil) or runtime.Goexit
goroutine 5 [running]:
testing.tRunner.func1(0x4560b0, 0xf)
/usr/local/go/src/testing/testing.go:792 +0x460
runtime.Goexit()
/usr/local/go/src/runtime/panic.go:397 +0x140
main.TestPanic.func1()
/tmp/sandbox284554843/main.go:18 +0x20
panic(0x121940, 0x165a58)
/usr/local/go/src/runtime/panic.go:513 +0x240
main.TestPanic(0x4560b0, 0xbab699fc)
/tmp/sandbox284554843/main.go:20 +0x60
testing.tRunner(0x4560b0, 0x1558f8)
/usr/local/go/src/testing/testing.go:827 +0x140
created by testing.(*T).Run
/usr/local/go/src/testing/testing.go:878 +0x3c0
我认为这是这一行的结果:
go/src/testing/testing.go
第813行 in bbae8d5
| | if!t.finished&&err==nil { |!t.finished
将返回 false,因为 t.Now()
标记了测试已完成,而 err 将为 nil,因为 runtime.Goexit()
在 t.FatalNow()
中正在恢复的是原始恐慌(而不是实际发生的恐慌)。
这防止了这一行上的预期恐慌:
go/src/testing/testing.go
第827行 in bbae8d5
| | panic(err) |
8条答案
按热度按时间ars1skjm1#
可能
FailNow
应该检查是否发生恐慌,但是为了区分panic
和runtime.GoExit
,我们必须尝试恢复它(#25448(评论)),这会破坏与原始panic
关联的堆栈信息。(我认为我在GopherCon上与@aclements讨论过这个警告...)km0tfn4u2#
CC @mpvl@josharian
bpsygsoo3#
我不明白
testing.FailNow
如何检测到恐慌。调用recover
是不起作用的,因为recover
只有在直接从延迟函数中调用时才返回非nil值,而如果它是被testing.FailNow
调用的话,就不会是这样的情况。然而,这又是怎么出现的呢?为什么要推迟对
FailNow
或Fatal
的调用?qlzsbp2j4#
嗯,好的观点。
FailNow
本身无法检查恐慌,但测试运行器可以。不幸的是,似乎
runtime.Goexit
目前会取消panic
(https://play.golang.org/p/xO5kMrMQkVS)。我不确定这是否是一个错误或Goexit
的预期行为。guykilcj5#
这个怎么会出现呢?为什么要推迟调用FailNow或Fatal?
被推迟的测试助手。例如,用于清理临时文件。
mbzjlibv6#
我可以将延迟函数中的调用更改为
t.Fatal
,然后返回,但我认为这应该可以使测试本身和延迟函数中的错误处理代码保持相同的结构。oo7oh9g97#
@seankhliao:
t.Cleanup
问题 #51395 是否肯定是这个问题的重复?我想知道
t.Cleanup
函数 introduced in 2020 是否可能是一个不同的路径,即使这个延迟函数的问题仍然存在。bq3bfh9z8#
Cleanup
是defer
的简写,并且只能实现为defer
。我不认为在不解决这个问题的情况下,你能修复Cleanup
。