testing/fixture/fixture.go

140 lines
3.5 KiB
Go

// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package fixture
import (
"testing"
"strconv"
"reflect"
)
type Test func(t *testing.T)
type F func(p Param) interface{}
type Ft struct {
*testing.T
params ParamReader
fixture F
data []interface{}
results ResultReader
}
func New(t *testing.T, f F, p ParamReader, r ResultReader) *Ft {
return &Ft{ T: t, params: p, fixture: f, results: r }
}
func (f *Ft) Fixture() []interface{} {
return f.data
}
func (f *Ft) Value() interface{} {
return f.data[len(f.data) - 1]
}
func (f *Ft) Result() interface{} {
return f.results.Values()[len(f.data) - 1]
}
func (f *Ft) RunWith(t Test) {
f.data = nil
for i, r := range(f.params.Values()) {
f.data = append(f.data, f.fixture(r))
f.Run(strconv.Itoa(i), t)
}
}
func (f *Ft) assertOp(value interface{}, o func (a interface{}, b interface{}) bool) {
r := f.Result()
if ! o(r, value) {
f.Errorf("Failure: value does not match expected result: [%s] != [%s]", r, value)
}
}
func (f *Ft) AssertStrEq(value string) {
f.assertOp(value, func (a interface{}, b interface{}) bool { return a.(string) == b.(string) })
}
func (f *Ft) AssertEq(value interface{}) {
cmpOp := func (a, b interface{}) bool {
rType := reflect.TypeOf(a)
switch rType.Name() {
case "float64", "float32":
return reflect.ValueOf(a).Convert(rType).Float() == reflect.ValueOf(b).Convert(rType).Float()
default:
return reflect.ValueOf(a).Convert(rType).Int() == reflect.ValueOf(b).Convert(rType).Int()
}
}
f.assertOp(value, cmpOp)
}
func (f *Ft) AssertGt(value interface{}) {
cmpOp := func (a, b interface{}) bool {
rType := reflect.TypeOf(a)
switch rType.Name() {
case "float64", "float32":
return reflect.ValueOf(a).Convert(rType).Float() > reflect.ValueOf(b).Convert(rType).Float()
default:
return reflect.ValueOf(a).Convert(rType).Int() > reflect.ValueOf(b).Convert(rType).Int()
}
}
f.assertOp(value, cmpOp)
}
func (f *Ft) AssertGe(value interface{}) {
cmpOp := func (a, b interface{}) bool {
rType := reflect.TypeOf(a)
switch rType.Name() {
case "float64", "float32":
return reflect.ValueOf(a).Convert(rType).Float() >= reflect.ValueOf(b).Convert(rType).Float()
default:
return reflect.ValueOf(a).Convert(rType).Int() >= reflect.ValueOf(b).Convert(rType).Int()
}
}
f.assertOp(value, cmpOp)
}
func (f *Ft) AssertLt(value interface{}) {
cmpOp := func (a, b interface{}) bool {
rType := reflect.TypeOf(a)
switch rType.Name() {
case "float64", "float32":
return reflect.ValueOf(a).Convert(rType).Float() < reflect.ValueOf(b).Convert(rType).Float()
default:
return reflect.ValueOf(a).Convert(rType).Int() < reflect.ValueOf(b).Convert(rType).Int()
}
}
f.assertOp(value, cmpOp)
}
func (f *Ft) AssertLe(value interface{}) {
cmpOp := func (a, b interface{}) bool {
rType := reflect.TypeOf(a)
switch rType.Name() {
case "float64", "float32":
return reflect.ValueOf(a).Convert(rType).Float() <= reflect.ValueOf(b).Convert(rType).Float()
default:
return reflect.ValueOf(a).Convert(rType).Int() <= reflect.ValueOf(b).Convert(rType).Int()
}
}
f.assertOp(value, cmpOp)
}
func (f *Ft) Assert() {
r := f.results.Values()
i := len(f.data) - 1
data := f.data[i]
res := r[i]
switch r[i].(type) {
case string:
data = string(f.data[i].([]byte))
res = string(r[i].(string))
}
if data != res {
f.Errorf("Failed value does not match expected result: [%s] != [%s]", f.data[i], r[i])
}
}