Documentation
¶
Overview ¶
Package tf is a microframework for parametrized testing of functions.
I wrote this because I was tired of creating a []struct{} fixture for most of my tests. I knew there had to be an easier and more reliable way.
It offers a simple and intuitive syntax for tests by wrapping the function:
// Remainder returns the quotient and remainder from dividing two integers.
func Remainder(a, b int) (int, int) {
return a / b, a % b
}
func TestRemainder(t *testing.T) {
Remainder := tf.Function(t, Remainder)
Remainder(10, 3).Returns(3, 1)
Remainder(10, 2).Returns(5, 0)
Remainder(17, 7).Returns(2, 3)
}
Assertions are performed with github.com/stretchr/testify/assert. If an assertion fails it will point to the correct line so you do not need to explicitly label tests.
The above test will output (in verbose mode):
=== RUN TestRemainder --- PASS: TestRemainder (0.00s) === RUN TestRemainder/Remainder#1 --- PASS: TestRemainder/Remainder#1 (0.00s) === RUN TestRemainder/Remainder#2 --- PASS: TestRemainder/Remainder#2 (0.00s) === RUN TestRemainder/Remainder#3 --- PASS: TestRemainder/Remainder#3 (0.00s) PASS
Index ¶
- func Function(t *testing.T, fn interface{}) func(args ...interface{}) *F
- func HTTPEmptyResponse(statusCode int) func(http.ResponseWriter, *http.Request)
- func HTTPJSONResponse(statusCode int, body interface{}) func(http.ResponseWriter, *http.Request)
- func HTTPStringResponse(statusCode int, body string) func(http.ResponseWriter, *http.Request)
- func NamedFunction(t *testing.T, fnName string, fn interface{}) func(args ...interface{}) *F
- func ServeHTTP(t *testing.T, handlerFunc http.HandlerFunc) func(HTTPTester)
- func SetEnv(t *testing.T, name, value string) (resetEnv func())
- func SetEnvs(t *testing.T, env map[string]string) (resetEnv func())
- type F
- type HTTPBeforeFunc
- type HTTPCheckFunc
- type HTTPFinallyFunc
- type HTTPServer
- type HTTPTest
- type HTTPTester
- type MultiHTTPTest
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Function ¶
Function wraps fn into F testing type and returns back function to which you can use as a regular function in e.g:
// Remainder returns the quotient and remainder from dividing two integers.
func Remainder(a, b int) (int, int) {
return a / b, a % b
}
func TestRemainder(t *testing.T) {
Remainder := tf.Function(t, Remainder)
Remainder(10, 3).Returns(3, 1)
Remainder(10, 2).Returns(5, 0)
Remainder(17, 7).Returns(2, 3)
}
func HTTPEmptyResponse ¶ added in v1.7.0
func HTTPEmptyResponse(statusCode int) func(http.ResponseWriter, *http.Request)
func HTTPJSONResponse ¶ added in v1.7.0
func HTTPJSONResponse(statusCode int, body interface{}) func(http.ResponseWriter, *http.Request)
func HTTPStringResponse ¶ added in v1.7.0
func NamedFunction ¶ added in v1.5.0
NamedFunction works the same way as Function but allows a custom name for the function to be set.
This is especially important when the function is anonymous, or it can be used for grouping tests:
Sum := tf.NamedFunction(t, "Sum1", Item.Add)
Sum(Item{1.3, 4.5}, 3.4).Returns(9.2)
Sum(Item{1.3, 4.6}, 3.5).Returns(9.4)
Sum = tf.NamedFunction(t, "Sum2", Item.Add)
Sum(Item{1.3, 14.5}, 3.4).Returns(19.2)
Sum(Item{21.3, 4.6}, 3.5).Returns(29.4)
func ServeHTTP ¶ added in v1.1.0
func ServeHTTP(t *testing.T, handlerFunc http.HandlerFunc) func(HTTPTester)
func SetEnv ¶ added in v1.6.0
SetEnv sets an environment variable and returns a reset function to ensure the environment is always returned to it's previous state:
resetEnv := tf.SetEnv(t, "HOME", "/somewhere/else") defer resetEnv()
If you would like to set multiple environment variables, see SetEnvs().
Types ¶
type F ¶
type F struct {
// contains filtered or unexported fields
}
F wrapper around a func which handles testing instance, agrs and reveals function name
func (*F) Errors ¶ added in v1.4.0
func (f *F) Errors(args ...interface{})
Errors check if function returns errors and match expectation you provided
BasicErrorer := tf.Function(t, func() error { return errors.New("some error") } )
BasicErrorer().Errors()
You also can provide strings to match message
AdvancedErrorer := tf.Function(t, func() error { return errors.New("some error") } )
AdvancedErrorer().Errors("some error")
Or you may provide your custom error type to check it bumps correctly
custom := MyCustomError{errors.New("some error")}
TypeErrorer := tf.Function(t, func() error { return custom } )
TypeErrorer().Errors(custom)
func (*F) False ¶ added in v1.2.0
func (f *F) False()
False matches is function returns false as a result
func Switch() bool {
return false
}
func TestSwitch(t *testing.T) {
Switch := tf.Function(t, Switch)
Switch().False()
}
type HTTPBeforeFunc ¶ added in v1.1.0
type HTTPBeforeFunc func(request *http.Request, response *httptest.ResponseRecorder)
type HTTPCheckFunc ¶ added in v1.1.0
type HTTPFinallyFunc ¶ added in v1.1.0
type HTTPFinallyFunc func(request *http.Request, response *httptest.ResponseRecorder)
type HTTPServer ¶ added in v1.7.0
func StartHTTPServer ¶ added in v1.7.0
func StartHTTPServer(port int) *HTTPServer
func (*HTTPServer) AddHandler ¶ added in v1.7.0
func (server *HTTPServer) AddHandler(path string, handler http.HandlerFunc) *HTTPServer
func (*HTTPServer) AddHandlers ¶ added in v1.7.0
func (server *HTTPServer) AddHandlers(handlers map[string]http.HandlerFunc) *HTTPServer
func (*HTTPServer) Endpoint ¶ added in v1.7.0
func (server *HTTPServer) Endpoint() string
type HTTPTest ¶ added in v1.1.0
type HTTPTest struct {
// Name is used as the test name. If it is empty the test name will be based
// on the Path.
Name string
// Method is the HTTP request method. If blank then "GET" will be used.
Method string
// Path used in the request. If the Path is blank then "/" is used because
// it is not possible to parse an empty path.
Path string
// RequestBody is the body for the request. You use a string as the body
// with:
//
// RequestBody: strings.NewReader("foo bar")
//
RequestBody io.Reader
// RequestHeaders will add or replace any header on the request.
RequestHeaders map[string]string
// ResponseHeaders will be checked from the response. Only the headers in
// ResponseHeaders will be checked and and their values must be exactly
// equal.
//
// If you need to do more sophisticated checking or headers you should use
// Check.
ResponseHeaders map[string]string
// ResponseBody will check the body of the response. ResponseBody must be
// not nil for the check to occur.
//
// You can check a string with:
//
// ResponseBody: strings.NewReader("foo bar")
//
ResponseBody io.Reader
// Status is the expected response HTTP status code. You can use one of the
// constants in the http package such as http.StatusOK. If Status is not
// provided then the response status will not be checked.
Status int
// Check is an optional function that is run before any other assertions. It
// receives the request and response so you can do any custom validation. If
// Check returns true the built in assertions will continue. Otherwise a
// return value of false means to stop checking the response because an
// error has already been found.
Check HTTPCheckFunc
// Finally is always called as a last event, even if the test fails. It is
// useful for guaranteeing cleanup or restoration of environments.
//
// The return value is ignored.
Finally HTTPFinallyFunc
// Before is run after the request and record is setup but before the
// request is executed.
Before HTTPBeforeFunc
}
type HTTPTester ¶ added in v1.1.0
type MultiHTTPTest ¶ added in v1.1.0
type MultiHTTPTest struct {
// Name is used as the test name. If it is empty the test name will be based
// on the Path.
Name string
// Before is run before any of the Steps begin.
Before func()
Steps []*HTTPTest
}
func (*MultiHTTPTest) TestName ¶ added in v1.1.0
func (ht *MultiHTTPTest) TestName() string
func (*MultiHTTPTest) Tests ¶ added in v1.1.0
func (ht *MultiHTTPTest) Tests() []*HTTPTest