如何在Go中测试退出代码,而不在退出代码不等于0时退出测试用例。

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

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 的测试总是取消测试,并因此取消所有后续迭代。这是我的代码:

  1. func Test_ShouldGetCorrectExitCode(t *testing.T) {
  2. testCases := []struct {
  3. args []string
  4. shouldBeValid bool
  5. }{
  6. {[]string{"0.1.0"}, false},
  7. {[]string{"v0.1.0"}, true},
  8. }
  9. for _, tc := range testCases {
  10. assert := assert.New(t)
  11. cmd := NewCmdValidate()
  12. cmd.SetArgs(tc.args)
  13. err := cmd.Execute()
  14. assert.Nil(err)
  15. }
  16. }

到目前为止,断言并不是很复杂,因为我无法按照预期运行测试。有人有什么想法,我如何在 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:

  1. func Test_ShouldGetCorrectExitCode(t *testing.T) {
  2. testCases := []struct {
  3. args []string
  4. shouldBeValid bool
  5. }{
  6. {[]string{"0.1.0"}, false},
  7. {[]string{"v0.1.0"}, true},
  8. }
  9. for _, tc := range testCases {
  10. assert := assert.New(t)
  11. cmd := NewCmdValidate()
  12. cmd.SetArgs(tc.args)
  13. err := cmd.Execute()
  14. assert.Nil(err)
  15. }
  16. }

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,而是让你的函数返回一个退出状态,这样你可以轻松地进行测试。示例代码如下:

  1. func main() {
  2. os.Exit(run())
  3. }
  4. func run() int {
  5. /* 在这里进行测试的操作 */
  6. }

然后在你的测试函数中:

  1. func TestRun(t *testing.T) {
  2. t.Run("应该成功", func(t *testing.T) {
  3. status := run()
  4. if status != 0 {
  5. t.Errorf("意外的退出状态:%d", status)
  6. })
  7. t.Run("应该失败", func(t *testing.T) {
  8. status := run()
  9. if status != 1 {
  10. t.Errorf("意外的状态码:%d", status)
  11. }
  12. })
  13. }
英文:

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:

  1. func main() {
  2. os.Exit(run())
  3. }
  4. func run() int {
  5. /* Things to test here */
  6. }

Then in your test:

  1. func TestRun(t *testing.T) {
  2. t.Run("should succeed", func(t *testing.T) {
  3. status := run()
  4. if status != 0 {
  5. t.Errorf("Unexpected exit status: %d", status)
  6. })
  7. t.Run("should fail", func(t *testing.T) {
  8. status := run()
  9. if status != 1 {
  10. t.Errorf("Unexpected status code: %d", status)
  11. }
  12. })
  13. }

huangapple
  • 本文由 发表于 2023年8月8日 20:31:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76859593.html
匿名

发表评论

匿名网友

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

确定