Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go test parameterized

Tags:

testing

go

In Python I can easily do

@pytest.mark.parametrize('input, expected', [(1, 2), [2, 3]])
def test_tutu(input, expected):
    assert input + 1 == expected

How can I do the same in Go, without writing myself a loop like this:

func tutu(a int) int {
    return a + 1
}

func Test_tutu(t *testing.T) {
    tests := []struct {
        input    int
        expected int
    }{
        {input: 1, expected: 2},
        {input: 2, expected: 3},
    }

    for _, tt := range tests {
        t.Run("", func(t *testing.T) {
            assert.Equal(t, tutu(tt.input), tt.expected)
        })
    }
}

So what would be the equivalent of this Python parametrize in Go?

def parametrize(all_args_name: str, all_values: List[Any], fn: Callable):
    args_name = all_args_name.split(',')
    for values in all_values:
        args = {k: v for k, v in zip(args_name, values)}
        fn(**args)
like image 428
raphaelauv Avatar asked Feb 28 '26 11:02

raphaelauv


2 Answers

The closest thing GO has is subtests, but you would still need to write the for loop, like you already did in the second example.

like image 140
Gilo Avatar answered Mar 04 '26 00:03

Gilo


I found a way using reflect

func parametrize[V any, T any](fn T, allValues [][]V) {
    v := reflect.ValueOf(fn)
    for _, a := range allValues {
        vargs := make([]reflect.Value, len(a))

        for i, b := range a {
            vargs[i] = reflect.ValueOf(b)
        }
        v.Call(vargs)
    }
}

func tutu(a int) int {
    return a + 1
}

func Test_tutu(t *testing.T) {
    testsArgs := [][]any{
        {t, 1, 2}, {t, 3, 4},
    }
    test := func(t *testing.T, input int, expected int) {
        assert.Equal(t, tutu(input), expected)
    }
    parametrize(test, testsArgs)
}
like image 24
raphaelauv Avatar answered Mar 04 '26 00:03

raphaelauv



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!