标准库错误的覆盖测试
Posted
技术标签:
【中文标题】标准库错误的覆盖测试【英文标题】:Coverage test for standard library errors 【发布时间】:2018-09-04 23:52:21 【问题描述】:我一直在尝试了解 Go 的内置测试框架并获得适当的测试覆盖率。
在我正在测试的其中一个文件中,我只获得了约 87% 的覆盖率:
coverage: 87.5% of statements
下面是测试中涉及的一段代码:
// Check that the working directory is set
if *strctFlags.PtrWorkDir == ""
// if the working directory is empty, set it to the current directory
strTemp, err := os.Getwd()
if err != nil
return "", errors.New("Could not get current working directory")
*strctFlags.PtrWorkDir = strTemp
else if stat, err := os.Stat(*strctFlags.PtrWorkDir); err != nil ||
!stat.IsDir()
// Existence check of the work dir
return "", errors.New("Specified directory \"" + *strctFlags.PtrWorkDir + "\" could not be found or was not a directory")
*strctFlags.PtrWorkDir, err = filepath.Abs(*strctFlags.PtrWorkDir)
if err != nil
return "", errors.New("Could not determine absolute filepath: " + err.Error())
根据 .out 文件,测试中未涵盖的部分是“if err != nil ”块,这将是标准库调用返回的错误。
虽然我认为除非出现硬件故障,否则标准库传递错误的可能性很小,但我认为最好知道错误在应用程序中得到了正确处理。此外,据我了解,检查返回的错误是惯用的 Go,因此我认为能够正确测试错误处理会很好。
人们如何处理上述情况的测试错误?是否有可能获得 100% 的覆盖率,或者我做错了什么或结构不正确?还是人们跳过测试这些条件?
【问题讨论】:
Some people skip them.。如果您出于某种原因必须拥有 100% 的测试覆盖率,那么您可能应该模拟/存根所有 stdlib 调用。 Go 标准库包是否具有 100% 的测试覆盖率?所有其他外部软件包是否具有 100% 的测试覆盖率?操作系统调用是否具有 100% 的测试覆盖率。硬件是否具有 100% 的测试覆盖率。是否测试了所有可能的整数和浮点算术?这需要多长时间?错误发生:Intel Pentium FDIV bug。等等。 100% 覆盖率测试是不可能的。 对于任何重要的代码(即任何使用 I/O 的代码),100% 的测试覆盖率是字面上的不可能,因为字面上有 无限代码执行路径的数量(即使假设相同的硬件等)。因此,以 100% 的覆盖率为目标是徒劳的。尽管通常可以让测试覆盖率工具(如 Go 提供的工具)报告 100%。但这不是很有意义,所以这不是一个有价值的目标。 为什么需要 100% 的覆盖率? @JoelCornett - 听起来不是很有必要,我在问是否有一种通用的方法可以以一种白痴的方式为 Go 测试这种场景,以及人们通常如何处理这种情况。 【参考方案1】:正如@flimzy 在他的回答中解释的那样,以 100% 的覆盖率为目标并不好,而是以有用的测试覆盖率为目标。
虽然您可以像这样对代码稍作修改来测试系统调用
package foo
// Get Working directory function
var osGetWd = os.Getwd
func GetWorkingDirectory() (string,error)
strTemp, err := osGetWd() // Using the function defined above
if err != nil
return "", errors.New("Could not get current working directory")
return strTemp,nil
在测试时
package foo
func TestGetWdError()
// Mocked function for os.Getwd
myGetWd := func() (string,error)
myErr := errors.New("Simulated error")
return "",myErr
// Update the var to this mocked function
osGetWd = myGetWd
// This will return error
val,err := GetWorkingDirectory()
这将帮助您实现 100% 的覆盖率
【讨论】:
看起来这就是我要找的东西!我知道 100% 的测试覆盖率并不是万无一失的,并且很欣赏这种观点背后的理念,但同时我觉得我已经了解了该语言的工作原理(我没有遇到过我之前可以通过这种方式将变量分配给函数...)【参考方案2】:在许多非硬件故障场景中,大多数标准库函数都可能会失败。您是否愿意测试这些是另一个问题。例如,对于os.Getwd()
,如果工作目录不存在,我可能会认为调用会失败(您可以努力测试这个场景)。
可能更有用(通常是更好的测试方法)是模拟这些调用,以便您可以在测试期间触发错误,以便您可以测试错误案例代码。
但是,出于对代码的热爱,请不要以 100% 的测试覆盖率为目标。瞄准有用的测试覆盖率。可以使工具报告 100% 的覆盖率而不覆盖有用的案例,并且可以覆盖有用的案例而不使工具报告 100%。
但是真的 100% 的覆盖率在大多数程序中是不可能的(即使是简单的“Hello World!”)。所以不要瞄准它。
【讨论】:
我有点同意,但这不是覆盖率计算解决方案的缺点吗?我的意思是,如果我覆盖了 100% 的逻辑,那么覆盖率报告工具不应该理解它,而不仅仅是老生常谈地计算代码行数吗? 缺点是假装任何覆盖工具的数字意味着更多。在现代计算机上,在任何现代程序中覆盖“100% 的逻辑”实际上是不可能的。 程序员可能理解,但很难向项目管理人员甚至客户解释(如果他们关心这些指标的话)。 现实很难向项目经理解释这一事实不是工具可以解决的。以上是关于标准库错误的覆盖测试的主要内容,如果未能解决你的问题,请参考以下文章