英文:
How to test for exit codes in go without exiting the testcase when the exit code is != 0
问题
我正在尝试为一个返回非零退出码的函数编写 Go 单元测试。我正在使用 cobra 开发一个 CLI 应用程序来验证语义版本。如果验证失败,我会返回一些 JSON 信息,并使用 os.Exit(1)
退出。
现在我想测试一下这个函数是否按预期工作。在我的测试中,我传入了一个应该成功并返回 0 的数据集,以及一个应该失败并返回 1 的数据集。但是应该返回 1 的测试总是取消测试,并因此取消所有后续迭代。这是我的代码:
func Test_ShouldGetCorrectExitCode(t *testing.T) {
testCases := []struct {
args []string
shouldBeValid bool
}{
{[]string{"0.1.0"}, false},
{[]string{"v0.1.0"}, true},
}
for _, tc := range testCases {
assert := assert.New(t)
cmd := NewCmdValidate()
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.Nil(err)
}
}
到目前为止,断言并不是很复杂,因为我无法按照预期运行测试。有人有什么想法,我如何在 Go 中测试退出码吗?
英文:
I'm trying to write a unit test in go for a function that returns non-zero exit codes. I'm developing a CLI app with cobra to validate semantic versions. In case a validation fails, I return some information in JSON and exit with os.Exit(1)
.
Now I want to test if this really works as intended. In my test I pass with one data set that should success and return 0 and one that should fail and return 1. But the test that should return 1 always cancels the test and hence cancels all following iterations. This is my code:
func Test_ShouldGetCorrectExitCode(t *testing.T) {
testCases := []struct {
args []string
shouldBeValid bool
}{
{[]string{"0.1.0"}, false},
{[]string{"v0.1.0"}, true},
}
for _, tc := range testCases {
assert := assert.New(t)
cmd := NewCmdValidate()
cmd.SetArgs(tc.args)
err := cmd.Execute()
assert.Nil(err)
}
}
So far the assertions are not really sophisticated because I don't get the test to run the way I expect. Anyone got an idea how I can test for exit codes in go?
答案1
得分: 4
最好的解决方案是在你的被测试函数中不要调用os.Exit
。一个好的实践是只在main()
函数中调用os.Exit
,而是让你的函数返回一个退出状态,这样你可以轻松地进行测试。示例代码如下:
func main() {
os.Exit(run())
}
func run() int {
/* 在这里进行测试的操作 */
}
然后在你的测试函数中:
func TestRun(t *testing.T) {
t.Run("应该成功", func(t *testing.T) {
status := run()
if status != 0 {
t.Errorf("意外的退出状态:%d", status)
})
t.Run("应该失败", func(t *testing.T) {
status := run()
if status != 1 {
t.Errorf("意外的状态码:%d", status)
}
})
}
英文:
The best solution is to not call os.Exit
from your function under test. A good practice can be to only call os.Exit
from main()
, and instead have your function return an exit status, which you can easily test for. Example:
func main() {
os.Exit(run())
}
func run() int {
/* Things to test here */
}
Then in your test:
func TestRun(t *testing.T) {
t.Run("should succeed", func(t *testing.T) {
status := run()
if status != 0 {
t.Errorf("Unexpected exit status: %d", status)
})
t.Run("should fail", func(t *testing.T) {
status := run()
if status != 1 {
t.Errorf("Unexpected status code: %d", status)
}
})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论