Home >Backend Development >Golang >Writing unit tests for generic functions in golang

Writing unit tests for generic functions in golang

WBOY
WBOYforward
2024-02-11 09:42:09968browse

在 golang 中为泛型函数编写单元测试

php Editor Banana brings you an article about writing unit tests for generic functions in Golang. Golang is a strongly typed programming language, however, its support for generics is relatively weak. Therefore, writing unit tests for generic functions can present some challenges. This article will introduce you to how to effectively write unit tests for generic functions in Golang to ensure the quality and reliability of your code. Whether you are a beginner or an experienced developer, this article will provide you with practical tips and methods to help you easily deal with unit testing of generic functions. Let’s take a look!

Question content

I have this simple generic function that retrieves a key from a map

// getmapkeys returns the keys of a map
func getmapkeys[t comparable, u any](m map[t]u) []t {
    keys := make([]t, len(m))
    i := 0
    for k := range m {
        keys[i] = k
        i++
    }
    return keys
}

I'm trying to write a table-driven unit test for it, like this:

var testunitgetmapkeys = []struct {
    name     string
    inputmap interface{}
    expected interface{}
}{
    {
        name:     "string keys",
        inputmap: map[string]int{"foo": 1, "bar": 2, "baz": 3},
        expected: []string{"foo", "bar", "baz"},
    },
    {
        name:     "int keys",
        inputmap: map[int]string{1: "foo", 2: "bar", 3: "baz"},
        expected: []int{1, 2, 3},
    },
    {
        name:     "float64 keys",
        inputmap: map[float64]bool{1.0: true, 2.5: false, 3.1415: true},
        expected: []float64{1.0, 2.5, 3.1415},
    },
}

However, the following code fails

func (us *unitutilsuite) testunitgetmapkeys() {
    for i := range testunitgetmapkeys {
        us.t().run(testunitgetmapkeys[i].name, func(t *testing.t) {
            gotkeys := getmapkeys(testunitgetmapkeys[i].inputmap)
        })
    }
}

and

type interface{} of testunitgetmapkeys[i].inputmap does not match map[t]u (cannot infer t and u)

This has been fixed with explicit conversion

gotKeys := getMapKeys(testUnitGetMapKeys[i].inputMap.(map[string]string))

Is there a way to automate these tests without having to perform explicit conversions for each input test variable?

Workaround

Note that unless your generic function performs some type-specific logic in addition to the generic logic, you will learn nothing by testing the function against different types. The function's general logic is the same for all types in the type parameter's type set, so it can be fully performed using a single type.

But if you want to run tests against different types, you can simply do the following:

var testUnitGetMapKeys = []struct {
    name string
    got  any
    want any
}{
    {
        name: "string keys",
        got:  getMapKeys(map[string]int{"foo": 1, "bar": 2, "baz": 3}),
        want: []string{"foo", "bar", "baz"},
    },
    {
        name: "int keys",
        got:  getMapKeys(map[int]string{1: "foo", 2: "bar", 3: "baz"}),
        want: []int{1, 2, 3},
    },
    {
        name: "float64 keys",
        got:  getMapKeys(map[float64]bool{1.0: true, 2.5: false, 3.1415: true}),
        want: []float64{1.0, 2.5, 3.1415},
    },
}

// ...

func (us *UnitUtilSuite) TestUnitGetMapKeys() {
    for _, tt := range testUnitGetMapKeys {
        us.T().Run(tt.name, func(t *testing.T) {
            if !reflect.DeepEqual(tt.got, tt.want) {
                t.Errorf("got=%v; want=%v", tt.got, tt.want)
            }
        })
    }
}

The above is the detailed content of Writing unit tests for generic functions in golang. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete