【问题标题】:How to run golang tests sequentially?如何按顺序运行 golang 测试?
【发布时间】:2015-09-21 00:04:44
【问题描述】:

当我运行go test 时,我的输出:

--- FAIL: TestGETSearchSuccess (0.00s)
        Location:       drivers_api_test.go:283
        Error:          Not equal: 200 (expected)
                                != 204 (actual)

--- FAIL: TestGETCOSearchSuccess (0.00s)
        Location:       drivers_api_test.go:391
        Error:          Not equal: 200 (expected)
                                != 204 (actual)

但是在我再次运行go test 之后,我的所有测试都通过了。

仅当我重置我的 mysql 数据库,然后第一次运行 go test 时,测试才会失败。

对于每个GET 请求,我之前都会执行POST 请求,以确保在数据库中创建了数据。

谁能帮助我确保测试按顺序运行?那就是POST请求在GET请求之前运行?

【问题讨论】:

    标签: testing go


    【解决方案1】:

    您不能/不应该依赖测试执行顺序。测试执行的顺序没有定义,使用testing flags 可以将测试排除在运行之外,因此您根本无法保证它们会运行。

    例如,以下命令将只运行名称包含'W' 字母的测试:

    go test -run W
    

    另外请注意,如果某些测试函数使用T.Parallel() 方法标记自己适合并行执行,go 工具将重新排序测试以首先运行非并行测试,然后在某些情况下并行运行并行测试(受控通过像-p这样的测试标志)。你可以在这个答案中看到这样的例子:Are tests executed in parallel in Go or one by one?

    测试应该彼此独立。如果一个测试函数有先决条件,则不能在另一个测试函数中完成/实现。

    在运行测试函数之前执行额外任务的选项:

    • 你可以把它放在测试函数本身中
    • 您可以将它放在包init() 函数中,在_test.go 文件本身中。这将在开始执行测试函数之前运行一次。
    • 您可以选择实现一个TestMain() 函数,该函数将首先被调用,并且您可以在调用M.Run() 以触发测试函数的执行之前进行额外的设置。
    • 您可以混合使用上述选项。

    init()TestMain() 包中,您应该检查您的数据库是否已初始化(插入了测试记录),如果没有,请插入测试记录。

    请注意,从 Go 1.7 开始,您可以使用定义子测试执行顺序的子测试。详情见博文:Using Subtests and Sub-benchmarks,以及testing包的包文档。

    【讨论】:

    • 这对于单元测试是有意义的,您正在测试模拟数据源,但是当您进行集成测试时,让集成测试按顺序运行可能是一个合理的要求。
    【解决方案2】:

    对于那些因为同时运行多个并发测试而遇到问题的人。我找到了一种方法来限制并行运行的最大测试数:

    go test -p 1
    

    这样,您的测试将一个接一个地按顺序运行。

    Source

    【讨论】:

    • 感谢您回答问题。
    【解决方案3】:

    除了ConveyGinkgo 等第三方库外,使用普通的 Golang 1.7,您可以按顺序运行测试。你可以阅读更多here

    func TestFoo(t *testing.T) {
        // <setup code>
        t.Run("A=1", func(t *testing.T) { ... })
        t.Run("A=2", func(t *testing.T) { ... })
        t.Run("B=1", func(t *testing.T) { ... })
        // <tear-down code>
    }
    

    你可以有条件地运行它们:

    go test -run ''      # Run all tests.
    go test -run Foo     # Run top-level tests matching "Foo", such as "TestFooBar".
    go test -run Foo/A=  # For top-level tests matching "Foo", run subtests matching "A=".
    go test -run /A=1    # For all top-level tests, run subtests matching "A=1".
    

    假设您从要测试的 REST api 获得了一个 user 包。您需要测试创建处理程序才能测试登录处理程序。通常我会在user_test.go

    type UserTests struct { Test *testing.T}
    func TestRunner(t *testing.T) {
    
        t.Run("A=create", func(t *testing.T) {
            test:= UserTests{Test: t}
            test.TestCreateRegularUser()
            test.TestCreateConfirmedUser()
            test.TestCreateMasterUser()
            test.TestCreateUserTwice()
        })
        t.Run("A=login", func(t *testing.T) {
            test:= UserTests{Test: t}
            test.TestLoginRegularUser()
            test.TestLoginConfirmedUser()
            test.TestLoginMasterUser()
        })
    
    }
    

    然后我可以将不会由任何_test.go 文件中的go test 命令执行的方法附加到 UserTest 类型

    func (t *UserTests) TestCreateRegularUser() {
        registerRegularUser := util.TableTest{
            Method:      "POST",
            Path:        "/iot/users",
            Status:      http.StatusOK,
            Name:        "registerRegularUser",
            Description: "register Regular User has to return 200",
            Body: SerializeUser(RegularUser),
        }
        response := util.SpinSingleTableTests(t.Test, registerRegularUser)
        util.LogIfVerbose(color.BgCyan, "IOT/USERS/TEST", response)
    }
    

    【讨论】:

    • 您能否通过这种方式对测试进行分组来确认订单实际上是受控的?文档说您可以控制并行性,但不一定会按照调用 t.Run 的顺序运行它们。比赛条件很难核实......如果我找到任何明确的证据,我会回复。
    • @threeve 他们肯定会按顺序运行。你基本上是以这种方式运行一个测试。
    【解决方案4】:

    实现这一目标的最佳方法是创建一个TestMain,如here 所示。

    import (
      "testing"
      "os"
    )
    
    func TestMain(m *testing.M) {
       // Do your stuff here
       os.Exit(m.Run())
    }
    

    【讨论】:

      猜你喜欢
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-24
      • 2015-12-18
      相关资源
      最近更新 更多