我刚开始使用来自PHP背景的PHPUnit测试进行测试。
在PHP中,非常讲道,您需要100%的覆盖率。在Go中,我所读到的关于测试的大多数内容似乎很少,没有诸如挑衅之类的东西。
例如我的小程序:
func main() { config = readConfig("config.json") } func readConfig(path string) Config { var cfg Config file, err := ioutil.ReadFile(path) if err != nil { log.Fatal(err) } err = json.Unmarshal(file, &cfg) if err != nil { log.Fatal(err) } return cfg } func TestCanReadConfig(t *testing.T) { cfg := readConfig("test_data/config.json") if cfg.Broker_pass != "test" || cfg.Broker_port != "3333" { t.Error("invalid config") } }
现在在我的示例中,我会遇到覆盖问题,因为在单元测试中根本没有覆盖main()(应该怎么办?)
而且两个log.Fatal()都没有涉及。
我的问题是我该如何准确地编写测试?我是否以一种不太严格的样式进行操作,而不是测试所有可能的场景?或者可以使用php中的php注释或可以 @expectedException \InvalidArgumentException 测试主要功能吗?如果不能,我可以以某种方式从覆盖率工具中忽略它吗?我应该考虑一个测试框架吗?大多数测试教程都很不错,但是非常简短,仅介绍简单的测试。
@expectedException \InvalidArgumentException
就其本身而言,这并不是Go的事情,它取决于您的偏好,但是:
一个。不要测试main。main应该只调用已测试的代码,最好在其他软件包中。对这些软件包提供尽可能多的代码覆盖率,并尽可能使main保持琐碎。无论覆盖范围如何,这都是一个好习惯。因此,这并不是真正的问题。
main
b。不要log.Fatal用于可测试的代码,只需返回错误。您可以保留log.Fatal应用程序初始化代码,即main-in :)。因此,如果main调用readConfig失败了,它只会返回一个错误(非常容易测试!)。应用程序的log.Fatal主要行为是main的工作- 配置读取器不应处理诸如确定是否应退出应用程序之类的事情,对吗?它只是读取配置,并告诉您是否成功。应用程序决定如何处理它。
log.Fatal
readConfig
因此您的代码可能如下所示:
func readConfig(path string) (Config, error) { var cfg Config file, err := ioutil.ReadFile(path) if err != nil { return cfg, err } err = json.Unmarshal(file, &cfg) if err != nil { return cfg, err } return cfg, nil } func main() { config, err := readConfig("config.json") if err != nil { log.Fatal(err) } }
现在,您已将逻辑与应用程序行为分开,并且readConfig可以完全测试。