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