Go

Go

Made by DeepSource

Inappropriate usage of t.Parallel() method GO-W6007

Bug risk
Critical

Using the t.Parallel() method can be tricky and ollowing are some common inappropriate usages of t.Parallel:

t.Parallel() is called in either a top-level test function or a sub-test function only — t.Parallel() is called in the sub-test function; it is post-processed by defer instead of t.Cleanup()

Here's a good blog post explaining how t.Parallel should be used.

The description of the Parallel() method from Go's official documentation:

func (t *T) Parallel()
    Parallel signals that this test is to be run in parallel with (and only
    with) other parallel tests. When a test is run multiple times due to use of
    -test.count or -test.cpu, multiple instances of a single test never run in
    parallel with each other.

Bad practice

func Test_TB2(t *testing.T) {
    teardown := setup("Test_TB2")
    t.Cleanup(teardown)
    t.Parallel() // "Test_TB2's subtests should call t.Parallel"

    tests := []struct { name string }{
        { name: "TB2_Sub1" },
        { name: "TB2_Sub2" },
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            call(tt.name)
        })
    }
}

func Test_Func1(t *testing.T) {
    teardown := setup("Test_Func1")
    t.Cleanup(teardown)

    // "Test_Func1 should call t.Parallel on the top level as well"

    t.Run("Func1_Sub1", func(t *testing.T) {
        call("Func1_Sub1")
        t.Parallel()
    })

    t.Run("Func1_Sub2", func(t *testing.T) {
        call("Func1_Sub2")
        t.Parallel()
    })
}

Recommended

func Test_TB2(t *testing.T) {
    teardown := setup("Test_TB2")
    t.Cleanup(teardown)
    t.Parallel()

    tests := []struct { name string }{
        { name: "TB2_Sub1" },
        { name: "TB2_Sub2" },
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            t.Parallel()
            call(tt.name)
        })
    }
}

func Test_Func1(t *testing.T) {
    teardown := setup("Test_Func1")
    t.Cleanup(teardown)
    t.Parallel()

    t.Run("Func1_Sub1", func(t *testing.T) {
        call("Func1_Sub1")
        t.Parallel()
    })

    t.Run("Func1_Sub2", func(t *testing.T) {
        call("Func1_Sub2")
        t.Parallel()
    })
}