英文:
Testing log.Fatalf in go?
问题
我想在Go代码中实现100%的测试覆盖率。我无法覆盖以下示例 - 有人可以帮我解决这个问题吗?
package example
import (
"io/ioutil"
"log"
)
func checkIfReadable(filename string) (string, error) {
_, err := ioutil.ReadFile(filename)
if err != nil {
log.Fatalf("无法读取文件...如何为此行添加覆盖测试?!?")
}
return "", nil
}
func main() {
checkIfReadable("dummy.txt")
}
一些针对此问题的虚拟测试:
package example
import (
"fmt"
"testing"
)
func TestCheckIfReadable(t *testing.T) {
someResult, err := checkIfReadable("dummy.txt")
if len(someResult) > 0 {
fmt.Println("这不会被打印")
t.Fail()
}
if err != nil {
fmt.Println("这不会被打印")
t.Fail()
}
}
func TestMain(t *testing.T) {
...
}
问题在于log.Fatalf
调用了os.Exit
,导致Go引擎停止运行。
- 我可以修改代码并用自己的库替换内置库,但这会使测试变得不太可靠。
- 我可以修改代码并创建一个代理、包装器等等,换句话说,这是一种非常复杂的机制,用于更改对
log.Fatalf
的所有调用。 - 我可以停止使用内置的log包...这等于在问"go内置"值多少?
- 我可以接受没有100%的覆盖率。
- 我可以将
log.Fatalf
替换为其他内容 - 但那么内置的log.Fatalf
有什么意义呢? - 我可以尝试操纵系统内存,并根据我的操作系统替换函数的内存地址(...),这样做一些模糊和不洁的事情。
- 其他任何想法吗?
英文:
I'd like to achieve 100% test coverage in go code. I am not able to cover the following example - can anyone help me with that?
package example
import (
"io/ioutil"
"log"
)
func checkIfReadable(filename string) (string, error) {
_, err := ioutil.ReadFile(filename)
if err != nil {
log.Fatalf("Cannot read the file... how to add coverage test for this line ?!?")
}
return "", nil
}
func main() {
checkIfReadable("dummy.txt")
}
Some dumy test for that:
package example
import (
"fmt"
"testing"
)
func TestCheckIfReadable(t *testing.T) {
someResult, err := checkIfReadable("dummy.txt")
if len(someResult) > 0 {
fmt.Println("this will not print")
t.Fail()
}
if err != nil {
fmt.Println("this will not print")
t.Fail()
}
}
func TestMain(t *testing.T) {
...
}
The issue is that log.Fatalf
calls os.Exit
and go engine dies.
- I could modify the code and replace built-in library with my own - what makes the tests less reliable.
- I could modify the code and create a proxy and a wrapper and a .... in other words very complex mechanism to change all calls to
log.Fatalf
- I could stop using built-in log package... what is equal to asking "how much is go built-in worth?"
- I could live with not having 100% coverage
- I could replace
log.Fataf
with something else - but then what is the point for built-inlog.Fatalf
? - I can try to mangle with system memory and depending on my OS replace memory address for the function (...) so do something obscure and dirty
- Any other ideas?
答案1
得分: 9
使用log.Print
而不是log.Fatal
,并返回在checkIfReadable
函数签名中声明的错误值。或者不处理错误并将其返回给更好处理错误的地方。
log.Fatal
函数严格用于报告程序的最后一次呼吸。
调用log.Fatal
比调用panic更糟糕(还有log.panic
),因为它不执行延迟调用。请记住,在Go语言中过度使用panic
被认为是一种不好的风格。
英文:
Use log.Print
instead of log.Fatal
and return the error value that you declared in signature of function checkIfReadable
. Or don't the error it and return it to some place that knows better how to handle it.
The function log.Fatal
is strictly for reporting your program's final breath.
Calling log.Fatal
is a bit worse than calling panic (there is also log.panic
), because it does not execute deferred calls. Remember, that overusing panic
in Go is considered a bad style.
答案2
得分: 0
获取100%的测试覆盖率并同时不失败的一个好方法是使用recover()
来捕获由log.Fatalf()
引发的panic。
这里是recover的文档。我认为它很适合你的使用情况。
英文:
A good way to get 100% test coverage and not fail at the same time is to use recover()
to catch the panic that is thrown by log.Fatalf()
.
Here are the docs for recover. I think it fits your use case nicely.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论