trial

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 18, 2020 License: MIT Imports: 10 Imported by: 0

README

Trial - Prove the Innocents of your code

GoDoc Build Status Go Report Card codecov

Framework to make tests easier to create, maintain and debug.

Philosophy

  • Tests should be written as Table Driven Tests with defined inputs and outputs
  • Each case must have a unique description
  • Each case should be fully isolated
    • doesn't depend on previous cases running
    • order of cases shouldn't matter

Getting Starting

Provide a TestFunc method and test Cases to trial.New and call Test with the *testing.T passed in.

 trial.New(fn testFunc, cases map[string]trial.Case).Test(t)

Alternatively to run as each case as a subtest

 trial.New(fn testFunc, cases trial.Cases).SubTest(t)
Case
  • Input interface{} - the input to the method being tested.
    • If the method has multiple parameters either embed the values in a struct or use trial.Args(args ...interface{}) to pass in multiple parameters
  • Expected interface{} - the expected output of the method being tested.
    • This is compared with the result from the TestFunc
  • ShouldErr bool - indicates the method should return an error
  • ExpectedErr error - verifies the method returns the same error as provided.
    • uses strings.Contains to check
    • also implies that the method should error so setting ShouldErr to true is not required
  • ShouldPanic bool - indicates the method should panic
TestFunc
  TestFunc  func(args ...interface{}) (result interface{}, err error)
  • args []interface{} - the arguments to be passed as parameters to the method.
    • case to the expected type, eg args[0].(string), args[1].(int)
  • output interface{} - the result from the test that is compared with Case.Expected
  • err error - any errors that occur during test, return nil if no errors occur.
Examples
Test a simple add method
func Add(i1, i2 int) int {
  return i1 + i2
}

func TestAdd(t *testing.T) {
  testFn := func(args ...interface{}) (interface{}, error) {
    return Add(args[0].(int), args[1].(int), nil
  }
  cases := trial.Cases{
    "Add two numbers":{
      Input: trial.Args(1,2),
      Expected: 3,
  }
  trial.New(fn, cases).Test(t)
  }

  // Output: PASS: "Add two numbers"
Test string to int conversion
func TestStrconv_Itoa(t *testing.T)
testFn := func(args ...interface{}) (interface{}, error) {
    return strconv.Itoa(args[0].(int))
}
cases :=trial.Cases{
  "valid int":{
    Input: "12",
    Expected: 12,
  },
  "invalid int": {
    Input: "1abe",
    ShouldErr: true,
  },
}
trial.New(fn, cases).Test(t)
}

// Output: PASS: "valid int"
// PASS: "invalid int"
Test divide method
func Divide(i1, i2 int) int {
  return i1/i2
}
func TestDivide(t *testing.T) {
  fn := func(args ...interface) (interface{}, error) {
    return Divide(args[0].(int), args[1].(int)), nil
  }
  cases := trial.Cases{
    "1/1":{
      Input: trial.Args(1,1),
      Expected: 1,
    },
    "6/2": {
      Input: trial.Args(6,2),
      Expected: 1,
    },
    "divide by zero": {
      Input: trial.Args(1,0),
      ShouldPanic: true,
    }
  }
  trial.New(fn, cases).Test(t)
}
// Output: PASS: "1/1"
// FAIL: "6/2"
// PASS: "divide by zero"

Compare Functions

used to compare two values to determine if they are considered equal and displayed a detailed string describing the differences found.

func(actual, expected interface{}) (equal bool, differences string)

override the default

trial.New(fn, cases).EqualFn(myComparer).Test(t)
Equal

This is the default comparer used, it is a wrapping for cmp.Equal with the AllowUnexported option set for all structs. This causes all fields (public and private) in a struct to be compared. (see https://github.com/google/go-cmp)

Contains ⊇

Checks if the expected value is contained in the actual value. The symbol ⊇ is used to donate a subset. ∈ is used to show that a value exists in a slice. Contains checks the following relationships

  • string ⊇ string
    • is the expected string contained in the actual string (strings.Contains)
  • string ⊇ []string
    • are the expected substrings contained in the actual string
  • []interface{} ⊇ interface{}
    • is the expected value found in the slice or array
  • []interface{} ⊇ []interface{}
    • is the expected slice a subset of the actual slice. all values in expected exist and are contained in actual.
  • map[key]interface{} ⊇ map[key]interface{}
    • is the expected map a subset of the actual map. all keys in expected are in actual and all values under that key are contained in actual

Helper Functions

The helper functions are convince methods for either ignoring errors on test setup or for capturing output for testing.

Output Capturing

Capture output written to log, stdout or stderr. Call ReadAll to get captured data as a single string. Call ReadLines to get captured data as a []string split by newline. Calling either method closes and reset the output redirection.

CaptureLog
  c := CaptureLog()
  // logic that writes to logs
  log.Print("hello")
  c.ReadAll() // -> returns hello

Note: log is reset to write to stderr

CaptureStdErr
  c := CaptureStdErr()
  // write to stderr
  fmt.Fprint(os.stderr, "hello\n")
  fmt.Fprint(os.stderr, "world")
  c.ReadLines() // []string{"hello","world"}
CaptureStdOut
  c := CaptureStdOut()
  // write to stdout
  fmt.Println("hello")
  fmt.Print("world")
  c.ReadLines() // []string{"hello","world"}
Time Parsing

convenience functions for getting a time value to test, methods panic instead of error

  • TimeHour(s string) - uses format "2006-01-02T15"
  • TimeDay(s string) - uses format "2006-01-02"
  • Times(layout string, values ...string)
  • TimeP(layout string, s string) returns a *time.Time
Pointer init

convenience functions for initializing a pointer to a basic type

  • int pointer
    • IntP, Int8P, Int16P, Int32P, Int64P
  • uint pointer
    • UintP, Uint8P, Uint16P, Uint32P, Uint64P
  • bool pointer - BoolP
  • float pointer
    • Float32P, Float64P
  • string pointer - StringP

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Args

func Args(args ...interface{}) interface{}

Args converts any number of parameters to an interface. generally used with Case's Input for multiple params

func BoolP added in v0.3.0

func BoolP(b bool) *bool

BoolP returns a pointer to a defined bool

func CaptureLog added in v0.1.1

func CaptureLog() *capture

CaptureLog overrides the log output for reading

func CaptureStdErr added in v0.1.1

func CaptureStdErr() *capture

CaptureStdErr redirects stderr for reading note this does not redirect log output

func CaptureStdOut added in v0.1.1

func CaptureStdOut() *capture

CaptureStdOut redirects stdout for reading

func CmpFuncs

func CmpFuncs(x, y interface{}) (b bool, s string)

CmpFuncs tries to determine if x is the same function as y.

func Contains added in v0.1.1

func Contains(x, y interface{}) (bool, string)

Contains determines if y is a subset of x. x is a string -> y is a string that is equal to or a subset of x (string.Contains) x is a slice or array -> y is contained in x x is a map -> y is a map and is contained in x

func ContainsFn

func ContainsFn(x, y interface{}) (bool, string)

ContainsFn has been renamed to Contains Deprecated:

func Equal

func Equal(actual, expected interface{}) (bool, string)

Equal use the cmp.Diff method to check equality and display differences. This method checks all unexpected values

func ErrType

func ErrType(err error) error

ErrType can be used with ExpectedErr to check that the expected err is of a certain type

func Float32P

func Float32P(f float32) *float32

Float32P returns a pointer to a defined float32

func Float64P

func Float64P(f float64) *float64

Float64P returns a pointer to a defined float64

func Int16P

func Int16P(i int16) *int16

Int16P returns a pointer to a defined int16

func Int32P

func Int32P(i int32) *int32

Int32P returns a pointer to a defined int32

func Int64P

func Int64P(i int64) *int64

Int64P returns a pointer to a defined int64

func Int8P

func Int8P(i int8) *int8

Int8P returns a pointer to a defined int8

func IntP

func IntP(i int) *int

IntP returns a pointer to a defined int

func StringP added in v0.2.0

func StringP(s string) *string

StringP returns a pointer to a defined string

func Time

func Time(layout, value string) time.Time

Time is a panic wrapper for the time.Parse method it returns a time.Time for the given layout and value

func TimeDay

func TimeDay(value string) time.Time

TimeDay is a helper method for parsing times with day precision. format 2006-01-02

func TimeHour

func TimeHour(value string) time.Time

TimeHour is a helper method for parsing times with hour precision. format 2006-01-02T15

func TimeP

func TimeP(layout, value string) *time.Time

TimeP return a pointers to a time.Time for the given layout and value. it panics on error

func Times

func Times(layout string, values ...string) []time.Time

Times is a panic wrapper for the time.Parse method it returns a time.Time slice for the given layout and values

func Uint16P added in v0.3.0

func Uint16P(i uint16) *uint16

Uint16P returns a pointer to a defined uint16

func Uint32P added in v0.3.0

func Uint32P(i uint32) *uint32

Uint32P returns a pointer to a defined uint32

func Uint64P added in v0.3.0

func Uint64P(i uint64) *uint64

Uint64P returns a pointer to a defined uint64

func Uint8P added in v0.3.0

func Uint8P(i uint8) *uint8

Uint8P returns a pointer to a defined uint8

func UintP added in v0.3.0

func UintP(i uint) *uint

UintP returns a pointer to a defined uint

Types

type Case

type Case struct {
	Input    interface{}
	Expected interface{}

	// testing conditions
	ShouldErr   bool  // is an error expected
	ExpectedErr error // the error that was expected (nil is no error expected)
	ShouldPanic bool  // is a panic expected
}

Case made during the trial of your code

type Cases

type Cases map[string]Case

Cases made during the trial

type CompareFunc added in v0.2.1

type CompareFunc func(actual, expected interface{}) (equal bool, differences string)

CompareFunc compares actual and expected to determine equality. It should return a human readable string representing the differences between actual and expected. Symbols with meaning: "-" elements missing from actual "+" elements missing from expected

type Comparer added in v0.2.1

type Comparer interface {
	Equals(interface{}) (bool, string)
}

Comparer interface is implemented by an object to check for equality and show any differences found

type TestFunc

type TestFunc func(args ...interface{}) (result interface{}, err error)

TestFunc a wrapper function used to setup the method being tested.

type Trial

type Trial struct {
	// contains filtered or unexported fields
}

Trial framework used to test different logical states

func New

func New(fn TestFunc, cases map[string]Case) *Trial

New trial for your code

func (*Trial) Comparer added in v0.2.1

func (t *Trial) Comparer(fn CompareFunc) *Trial

Comparer override the default comparison function. see Contains(x, y interface{}) (bool, string) see Equals(x, y interface{}) (bool, string)

func (*Trial) EqualFn

func (t *Trial) EqualFn(fn CompareFunc) *Trial

EqualFn override the default comparison method used. see ContainsFn(x, y interface{}) (bool, string) depricated

func (*Trial) SubTest added in v0.2.0

func (t *Trial) SubTest(tst testing.TB)

SubTest runs all cases as individual subtests

func (*Trial) Test

func (t *Trial) Test(tst testing.TB)

Test all cases provided

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL