我对 Go 1.18 感到兴奋,并想测试新的泛型特性。 使用起来感觉很整洁,但我偶然发现了一个问题:
如何对泛型函数进行表测试?
我想出了这个 code ,但我需要重新声明每个函数的测试逻辑,因为我无法实例化 T
值。
(在我的项目中,我使用结构而不是 string
和 int
。只是不想包含它们,因为它已经有足够的代码)
你会如何解决这个问题?
编辑: 这是代码:
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
type Item interface {
int | string
}
type store[T Item] map[int64]T
// add adds an Item to the map if the id of the Item isn't present already
func (s store[T]) add(key int64, val T) {
_, exists := s[key]
if exists {
return
}
s[key] = val
}
func TestStore(t *testing.T) {
t.Run("ints", testInt)
t.Run("strings", testString)
}
type testCase[T Item] struct {
name string
start store[T]
key int64
val T
expected store[T]
}
func testString(t *testing.T) {
t.Parallel()
tests := []testCase[string]{
{
name: "empty map",
start: store[string]{},
key: 123,
val: "test",
expected: store[string]{
123: "test",
},
},
{
name: "existing key",
start: store[string]{
123: "test",
},
key: 123,
val: "newVal",
expected: store[string]{
123: "test",
},
},
}
for _, tc := range tests {
t.Run(tc.name, runTestCase(tc))
}
}
func testInt(t *testing.T) {
t.Parallel()
tests := []testCase[int]{
{
name: "empty map",
start: store[int]{},
key: 123,
val: 456,
expected: store[int]{
123: 456,
},
},
{
name: "existing key",
start: store[int]{
123: 456,
},
key: 123,
val: 999,
expected: store[int]{
123: 456,
},
},
}
for _, tc := range tests {
t.Run(tc.name, runTestCase(tc))
}
}
func runTestCase[T Item](tc testCase[T]) func(t *testing.T) {
return func(t *testing.T) {
tc.start.add(tc.key, tc.val)
assert.Equal(t, tc.start, tc.expected)
}
}
最佳答案
I need to redeclare my testing logic over each function
正确。
你的函数 runTestCase[T Item](tc testCase[T])
已经提供了合理的抽象级别。正如您所做的那样,您可以在其中放置一些关于开始测试和验证预期结果的通用逻辑。然而,仅此而已。
被测试的通用类型(或函数)迟早必须用某种具体类型实例化,并且一个测试表只能包含这些类型中的任何一种 — 或 interface{}
/any
,您不能使用它来满足特定约束,例如 int | string
.
但是,您不需要总是测试每个可能的类型参数。泛型的目的是编写适用于任意类型的代码,特别是约束的目的是编写支持相同操作的任意类型的代码。
我建议仅当代码使用具有不同含义的运算符时才为不同类型编写单元测试。例如:
+
数字(求和)和字符串(连接)的运算符<
和>
用于数字(更大、更小)和字符串(按字典顺序在之前或之后)
另见 this OP 试图做类似的事情
关于unit-testing - 表测试 Go 泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70980279/