How to write a table driven test for a generic method?

Viewed 31

I have a simple generic method that looks like this:

func L[T ~string](s T) string {
   return string(s)
}

I can easily exercise this in code like so:

type T string


L(T("foo"))
L("foo")

I'm trying to figure out how to design a table driven test to also exercise the method. Where I'm getting caught up is in the generic field needed in the struct. So I have a test that looks something like:

TestL(t *testing.T) {
  tests := []struct{
     in ??? // This is where I'm stuck
     want string
  }{
     { in: T("foo"), want: "foo" },
     { in: "foo", want: "foo" },
  }
  for _, tc := range tests {
    t.Run("", func(t *testing.T) {
      if got := L(tc.in); got != tc.want {
         t.Errorf("got %s, want %s", got, tc.want)
      }
    })
  }
}

I tried doing something like [][T ~string]struct{ in T } but that apparently can't work with the anonymous struct, so then I pulled it into its own type type test[T ~string] struct.

This sort of works but requires me to instantiate a specific type: tests := []test[string]{} or tests := []test[T]{}. I could do multiple testing blocks for each type but -

I'm looking for a way to ideally, declare an anonymous struct tests := []struct{}{}, and allow that struct to take the generic values that satisfy the ~string constraint without needing multiple calls.

1 Answers

Each instantiation of a generic type is a different type, so there may not be a good way of doing this. One way I can think of is the following:

tests := []struct{
     in func() string
     want string
  }{
     { in: func() {return L(T("foo"))} , want: "foo" },
     { in: func() {return L("foo")} , want: "foo" },
  }
Related