Last active
December 17, 2022 00:09
-
-
Save veggiemonk/e61da4af14cfda4e8f7f50c44526fe51 to your computer and use it in GitHub Desktop.
go testing framework with generics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testutils | |
import "testing" | |
func equal[T comparable](a, b T) bool { | |
return a == b | |
} | |
func Equal[T comparable](t *testing.T, expected, actual T) { | |
if !equal(expected, actual) { | |
t.Fatalf("Expected %v, got %v", expected, actual) | |
} | |
} | |
func NotEqual[T comparable](t *testing.T, expected, actual T) { | |
if equal(expected, actual) { | |
t.Fatalf("Expected %v, got %v", expected, actual) | |
} | |
} | |
func Nil(t *testing.T, obj any) { | |
if obj != nil { | |
t.Fatalf("Expected nil, got %v", obj) | |
} | |
} | |
func NotNil(t *testing.T, obj any) { | |
if obj == nil { | |
t.Fatalf("Expected not nil, got nil") | |
} | |
} | |
func contains[T comparable](haystack []T, needle T) bool { | |
for _, item := range haystack { | |
if item == needle { | |
return true | |
} | |
} | |
return false | |
} | |
func Contains[T comparable](t *testing.T, haystack []T, needle T) { | |
if !contains(haystack, needle) { | |
t.Fatalf("Expected %v to contain %v", haystack, needle) | |
} | |
} | |
func NotContains[T comparable](t *testing.T, haystack []T, needle T) { | |
if contains(haystack, needle) { | |
t.Fatalf("Expected %v to not contain %v", haystack, needle) | |
} | |
} | |
func True(t *testing.T, condition bool) { | |
if !condition { | |
t.Fatalf("Expected true, got false") | |
} | |
} | |
func False(t *testing.T, condition bool) { | |
if condition { | |
t.Fatalf("Expected false, got true") | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package testutils | |
import ( | |
"path/filepath" | |
"reflect" | |
"runtime" | |
"strconv" | |
"strings" | |
"testing" | |
"github.com/google/go-cmp/cmp" | |
"github.com/google/go-cmp/cmp/cmpopts" | |
) | |
// Diff compares two items and returns a human-readable diff string. If the | |
// items are equal, the string is empty. | |
func Diff[T any](got, want T) string { | |
opts := cmp.Options{ | |
cmp.Exporter(func(reflect.Type) bool { return true }), | |
cmpopts.EquateEmpty(), | |
} | |
diff := cmp.Diff(got, want, opts...) | |
if diff != "" { | |
return "\n-got +want\n" + diff | |
} | |
return "" | |
} | |
// Callers prints the stack trace of everything up til the line where Callers() | |
// was invoked. | |
func Callers() string { | |
var pc [50]uintptr | |
n := runtime.Callers(2, pc[:]) //nolint:gomnd // skip runtime.Callers + Callers | |
callsites := make([]string, 0, n) | |
frames := runtime.CallersFrames(pc[:n]) | |
for frame, more := frames.Next(); more; frame, more = frames.Next() { | |
callsites = append(callsites, frame.File+":"+strconv.Itoa(frame.Line)) | |
} | |
callsites = callsites[:len(callsites)-1] // skip testing.tRunner | |
if len(callsites) == 1 { | |
return "" | |
} | |
var b strings.Builder | |
for i := len(callsites) - 1; i >= 0; i-- { | |
if b.Len() > 0 { | |
b.WriteString(" -> ") | |
} | |
b.WriteString(filepath.Base(callsites[i])) | |
} | |
return "\n" + b.String() + ":" | |
} | |
func AssertEqual[C comparable](t *testing.T, got, want C) { | |
if diff := Diff(got, want); diff != "" { | |
t.Error(Callers(), diff) | |
} | |
} | |
// func TestExample(t *testing.T) { | |
// type TT struct { | |
// got string | |
// want string | |
// } | |
// | |
// assert := func(t *testing.T, tt TT) { | |
// if diff := Diff(tt.got, tt.want); diff != "" { | |
// t.Error(Callers(), diff) | |
// } | |
// } | |
// | |
// t.Run( | |
// "1", func(t *testing.T) { | |
// t.Parallel() | |
// assert(t, TT{"lorem ipsum dolor amet", "lorem ipsum dolor sit amet"}) | |
// }, | |
// ) | |
// | |
// t.Run( | |
// "2", func(t *testing.T) { | |
// t.Parallel() | |
// assert(t, TT{"the quick fox jumped over lazy dog", "the quick brown fox jumped over the lazy dog"}) | |
// }, | |
// ) | |
// | |
// t.Run( | |
// "2", func(t *testing.T) { | |
// t.Parallel() | |
// assert(t, TT{"Sphinx of black quartz judge my vow", "Sphinx of black quartz, judge my vow"}) | |
// }, | |
// ) | |
// } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment