【问题标题】:Run tests programmatically in Go在 Go 中以编程方式运行测试
【发布时间】:2021-08-08 13:51:51
【问题描述】:

我想在 Go 中以编程方式运行一些测试。我正在尝试使用testing.RunTests,但它会引发运行时错误。我也不知道代码有什么问题。

这就是它的样子:

package main

import (
    "testing"
)

func TestSomething(t *testing.T) {
    if false {
        t.Error("This is a mocked failed test")
    }
}

func main() {
    testing.RunTests(func(pat, str string) (bool, error) { return true, nil },
        []testing.InternalTest{
            {"Something", TestSomething}},
    )
}

游乐场链接:https://play.golang.org/p/BC5MG8WXYGD

我得到的错误是:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4b5948]

【问题讨论】:

    标签: go testing


    【解决方案1】:

    首先,运行测试应该通过go test 命令来完成。

    testing 包中导出的某些类型和函数用于测试框架,而不适合您。引用testing.RunTests():

    RunTests 是一个内部函数,但因为是跨包而被导出;它是“go test”命令实现的一部分。

    它“必须”被导出,因为它早于“内部”包。

    那里。您已收到警告。

    如果您仍想这样做,请致电 testing.Main() 而不是 testing.RunTests()

    例如:

    func TestGood(t *testing.T) {
    }
    
    func TestBad(t *testing.T) {
        t.Error("This is a mocked failed test")
    }
    
    func main() {
        testing.Main(
            nil,
            []testing.InternalTest{
                {"Good", TestGood},
                {"Bad", TestBad},
            },
            nil, nil,
        )
    }
    

    哪个会输出(在Go Playground上试试):

    --- FAIL: Bad (0.00s)
        prog.go:11: This is a mocked failed test
    FAIL
    

    如果您想捕捉测试的成功,请使用“较新的”testing.MainStart() 函数。

    首先我们需要一个辅助类型(它实现了一个未导出的接口):

    type testDeps struct{}
    
    func (td testDeps) MatchString(pat, str string) (bool, error)   { return true, nil }
    func (td testDeps) StartCPUProfile(w io.Writer) error           { return nil }
    func (td testDeps) StopCPUProfile()                             {}
    func (td testDeps) WriteProfileTo(string, io.Writer, int) error { return nil }
    func (td testDeps) ImportPath() string                          { return "" }
    func (td testDeps) StartTestLog(io.Writer)                      {}
    func (td testDeps) StopTestLog() error                          { return nil }
    func (td testDeps) SetPanicOnExit0(bool)                        {}
    

    现在使用它:

    m := testing.MainStart(testDeps{},
        []testing.InternalTest{
            {"Good", TestGood},
            {"Bad", TestBad},
        },
        nil, nil,
    )
    
    result := m.Run()
    fmt.Println(result)
    

    哪些输出(在Go Playground 上试试):

    --- FAIL: Bad (0.00s)
        prog.go:13: This is a mocked failed test
    FAIL
    1
    

    如果所有测试都通过,result 将是0

    【讨论】:

    • 谢谢,“如果你想捕捉测试的成功”是什么意思?
    • @ninesalt 如果您想从主应用程序中了解测试是通过还是失败,例如你想以不同的方式取得成功。
    • 啊,好吧。
    • 如果之前的测试出现恐慌,我有什么办法可以让其他测试运行?这似乎没有发生
    • @ninesalt 一个测试函数不应该恐慌,这不是一个正常的测试函数。您可以在将其添加到 []InternalTest 切片之前将其包装在另一个函数中(在发生恐慌时恢复)。
    【解决方案2】:

    有一种方法可以触发命令

    go test -v -json 
    

    通过exec.Command在代码内部,初始化一个读取器,读取stdout,然后解析输出。

    这个答案是https://github.com/AlekSi给出的 非常感谢,谢谢 Aleksi!

    https://github.com/FerretDB/dance/blob/main/internal/gotest/gotest.go

    【讨论】:

      猜你喜欢
      • 2020-11-01
      • 1970-01-01
      • 2012-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      • 1970-01-01
      相关资源
      最近更新 更多