单元测试在循环中执行致命流代码

MithunS

我正在尝试向go cli代码添加测试。代码有很多log.Fatal流程。有点谷歌搜索将我引到这里,所以我遵循了它,并使测试正常进行。但是,按照我的测试方式,它们被设置为使用不同的参数在循环中运行要测试的函数。

这是测试代码

func TestGetXXX_FatalFlow(t *testing.T) {
    type args struct {
        varA string
        varB    string
    }
    tests := []struct {
        name     string
        args     args
        expected string
    }{
        {
            name:     "Scenario 1: varA and varB both blank",
            args:     args{},
            expected: "message1",
        },
        {
            name: "Scenario 2: varA and varB not blank but invalid",
            args: args{
                varA: "somevalueA",
                varB: "somevalueB",
            },
            expected: "message2",
        },
     }
    for _, tt := range tests {

        t.Run(tt.name, func(t *testing.T) {

            // Only run the failing part when a specific env variable is set
            if os.Getenv("BE_CRASHER") == "1" {
                GetXXX(tt.args.serverName, tt.args.address)
                return
            }

            // Start the actual test in a different subprocess
            cmd := exec.Command(os.Args[0], "-test.run=TestGetXXX_FatalFlow")
            cmd.Env = append(os.Environ(), "BE_CRASHER=1")
            stdout, _ := cmd.StderrPipe()
            if err := cmd.Start(); err != nil {
                t.Fatal(err)
            }

            // Check that the log fatal message is what we expected
            gotBytes, _ := ioutil.ReadAll(stdout)

            if !strings.Contains(string(gotBytes), tt.expected) {
                t.Fatalf("Unexpected log message. Got %s but should contain %s", strippedMsg, tt.expected)
            }

            // Check that the program exited
            cmd.Env = append(os.Environ(), "BE_CRASHER=0")
            err = cmd.Wait()
            if e, ok := err.(*exec.ExitError); !ok || e.Success() {
                t.Fatalf("Process ran with err %v, want exit status 1", err)
            }
        })
    }
}

我遇到的问题是,我觉得我的方法GetXXX从未用第二对输入变量调用,以某种方式,方法GetXXX一直只用tests数组中的第一对参数来调用。我不确定它是否是因为这会产生一个子进程。

任何帮助将不胜感激。谢谢

阿德里安

如果遍历代码,您会发现它正在按预期运行:

  1. 外部测试运行开始,循环测试用例,未设置env var,因此对于每次迭代,它都会派出一个新go test流程。
  2. 运行相同的测试功能,新工艺开始遍历测试的情况下,的环境变量设置,所以对于每一次迭代,它调用GetXXX,它崩溃。

您将在此处的步骤2中看到,对于每次迭代,子进程都会运行第一个测试用例,该用例将崩溃,并且永远不会到达第二个用例。父级中的循环迭代是无关紧要的-它永远不会将测试用例的任何参数传递给子进程,因此子级不知道父级认为正在测试的测试用例。它再次迭代案例本身,但仅在崩溃前设法执行第一个案例。

通常,我建议不要使用这种结构(go test派生出新的结构go test),也建议不要在代码中的任何地方出现致命错误。对于99%的情况,error当出现问题时,您的函数应返回对于真正不可恢复的致命错误,您应该使用panic,然后可以测试使用recoverlog.Fatal(我猜这是您正在使用的)只是打印一条日志消息,然后调用os.Exit,这使得几乎无法进行测试(如您所见)。

如果真的不能正确地正确构造程序,那么作为最后的选择,您可以这样做(未经测试,但我希望它能使您明白这一点):

crasher := os.Getenv("BE_CRASHER")
if crasher == "" {  // Parent process
    for idx := range tests {

        t.Run(tt.name, func(t *testing.T) {

            // Start the actual test in a different subprocess
            cmd := exec.Command(os.Args[0], "-test.run=TestGetXXX_FatalFlow")
            cmd.Env = append(os.Environ(), fmt.Sprintf("BE_CRASHER=%d", idx))
            stdout, _ := cmd.StderrPipe()
            if err := cmd.Start(); err != nil {
                t.Fatal(err)
            }

            // Validate child process did as expected yadda yadda
        })
    }
} else {  // Child process
    idx, err := strconv.Atoi(crasher)
    if err != nil {
        panic(err)
    }
    tt := tests[idx]
    GetXXX(tt.args.serverName, tt.args.address)
    return
}

这通过让父级迭代测试用例来进行更改,并在派生子级时使用env var告诉子级运行哪种情况然后,该子项运行指定的案例。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Java 8 Lambdas的单元测试代码

来自分类Dev

单元测试代码的最佳位置

来自分类Dev

提供C ++代码的单元测试

来自分类Dev

代码合同的单元测试应该如何?

来自分类Dev

从单元测试执行开始构建

来自分类Dev

Jacoco涵盖单元测试代码

来自分类Dev

最小起订量/单元测试除非单步执行代码,否则无法捕获异常

来自分类Dev

关闭第三方代码的单元测试执行

来自分类Dev

在单元测试中循环

来自分类Dev

单元测试代码覆盖率

来自分类Dev

Web Worker的单元测试代码

来自分类Dev

单元测试框架内部的While循环

来自分类Dev

依赖常量值的单元测试代码

来自分类Dev

单元测试错误地从启动视图控制器执行代码

来自分类Dev

如何在多线程方案中对仅执行一次的代码进行单元测试?

来自分类Dev

无限循环的单元测试

来自分类Dev

单元测试模板代码

来自分类Dev

创建目录的单元测试代码

来自分类Dev

单元测试C生成python代码

来自分类Dev

使代码可测试-单元测试

来自分类Dev

单元测试事件处理程序的代码

来自分类Dev

从单元测试执行开始构建

来自分类Dev

关闭第三方代码的单元测试执行

来自分类Dev

如何对Alex代码进行单元测试?

来自分类Dev

在`for`循环中的Mocha单元测试和断言

来自分类Dev

单元测试代码活动工作流

来自分类Dev

证明代码避免无限循环的单元测试

来自分类Dev

grunt 测试 - 致命错误:尚未实施单元测试

来自分类Dev

Grails 如何对异常执行单元测试