I'm not sure I'm naming the question correctly, if I'm not, I'm willing to modify.

I have a test like this:

func TestMyStruct(t *testing.T) {
    tests := []struct {
        testcase string
        setup    func()
    }{
        testcase: "test1",
        setup: func() {
          // if setup fail, call t.Fatal()
          t.Fatal()
        },
    }

    for _, test := range tests {
        t.Run(test.testcase, func(t *testing.T) {
            // setup:
            test.setup()

            // action:

            // assertions:
        })
    }
}

I could write in in another way, passing t into inner setup function:

func TestMyStruct(t *testing.T) {
        tests := []struct {
            testcase string
            setup    func(t *testing.T)
        }{
            testcase: "test1",
            setup: func(t *testing.T) {
               // if setup fail, call t.Fatal()
               t.Fatal()
            },
        }

        for _, test := range tests {
            t.Run(test.testcase, func(t *testing.T) {
                // setup:
                test.setup(t)

                // action:

                // assertions:
            })
        }
    }

My question is which way is preferred and why.

1 Answers

1
Eli Bendersky On Best Solutions

In the fist example t inside the setup function refers to the main test passed into TestMyStruct.

In the second example t inside the setup function refers to its own t argument which is passed on as a subtest from t.Run.

These are different, and it depends which test you want to fail - the main test or a subtest.

[expanding on @Peter's comment and marking as community wiki]