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!
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?
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!