Testing log.Fatalf in go?

huangapple go评论77阅读模式
英文:

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-in log.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.

huangapple
  • 本文由 发表于 2017年8月21日 21:03:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/45797858.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定