tesuto

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Oct 17, 2022 License: BSD-2-Clause Imports: 15 Imported by: 0

README

tesuto GoDoc

import "github.com/guregu/tesuto"

tesuto is a little library for testing against HTTP services. It glues together the standard library's net/http/httptest package and Google's go-cmp with functional options eliminating much tedious boilerplate.

Example

func TestGreeting(t *testing.T) {
	type Response struct {
		Msg  string    `json:"msg"`
		Time time.Time `json:"time"`
	}

	mux := http.NewServeMux()
	// example API we will test against
	mux.HandleFunc("/greet", func(w http.ResponseWriter, r *http.Request) {
		// return 405 Method Not Allowed if not a POST request
		if r.Method != http.MethodPost {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}
		// return 400 Bad Request if name is missing
		name := r.FormValue("name")
		if name == "" {
			w.WriteHeader(http.StatusBadRequest)
			return
		}
		// return 200 OK and response JSON
		w.Header().Set("Content-Type", "application/json")
		resp := Response{
			Msg:  fmt.Sprintf("hello %s", name),
			Time: time.Now(),
		}
		if err := json.NewEncoder(w).Encode(resp); err != nil {
			panic(err)
		}
	})
	server := httptest.NewServer(mux)
	defer server.Close()

	suite := tesuto.New(server)

	t.Run("greet: happy path", suite.Test(
		"POST",
		"/greet",
		tesuto.WithFormInput(url.Values{
			"name": {"greg"},
		}),
		tesuto.ExpectStatusCode(http.StatusOK),
		tesuto.ExpectHeader("Content-Type", "application/json"),
		tesuto.ExpectJSONResponse(Response{
			Msg:  "hello greg",
			Time: time.Now(),
		}, tesuto.EquateApproxTime(10*time.Second)), // consider times within 10 seconds to be equal
	))

	t.Run("greet: missing name param", suite.Test(
		"POST",
		"/greet",
		tesuto.ExpectStatusCode(http.StatusBadRequest),
	))

	t.Run("greet: wrong method", suite.Test(
		"GET",
		"/greet",
		tesuto.ExpectStatusCode(http.StatusMethodNotAllowed),
	))
}

Handy error messages make it easy to see where tests fail:

--- FAIL: TestPost (0.00s)
    --- FAIL: TestPost/greet:_happy_path (0.00s)
        tesuto.go:83: output:
             {"msg":"hello greg","time":"2022-01-01T19:23:44.0272386+09:00"}

        tesuto.go:114: [POST /greet] output mismatch (-want +got):
              tesuto_test.Response{
            -   Msg:  "hello bob",
            +   Msg:  "hello greg",
                Time: s"2022-01-01 19:23:44.0272386 +0900 JST",
              }

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EquateApproxTime

func EquateApproxTime(margin time.Duration) cmp.Option

func IgnoreField

func IgnoreField(name string) cmp.Option

IgnoreField is a comparison option that ignores the given field, like "Foo" or "Foo.Bar".

func IgnoreUnexported

func IgnoreUnexported(types ...interface{}) cmp.Option

func NotEmpty

func NotEmpty(name string) cmp.Option

NotEmpty is a comparison option that requires both things to not be empty. That is, different from their zero values.

func ParseHTML

func ParseHTML(t *testing.T, body string) *goquery.Document

func ParseURL

func ParseURL(t *testing.T, href string) *url.URL

func SortSlices

func SortSlices(lessFunc interface{}) cmp.Option

Types

type HTTP

type HTTP struct {
	*httptest.Server
}

HTTP is a test suite wrapper around httptest.Server.

func New

func New(server *httptest.Server) HTTP

New creates a new test suite.

func (HTTP) Test

func (h HTTP) Test(method string, path string, opts ...TestOption) func(*testing.T)

Test returns a test function suitable for running with t.Run.

type TestOption

type TestOption func(*testCase)

func ExpectHeader

func ExpectHeader(name, value string) TestOption

ExpectStatusCode specifies an expected HTTP header of the response.

func ExpectJSONResponse

func ExpectJSONResponse(output interface{}, compareOpt ...cmp.Option) TestOption

ExpectJSONResponse specifies a JSON object that should match the response. The response will be decoded into the same type as the specified output and compared. Comparison options can be specified.

func ExpectRawResponse

func ExpectRawResponse(body []byte) TestOption

ExpectRawResponse specifies the exact body expected of the response.

func ExpectStatusCode

func ExpectStatusCode(code int) TestOption

ExpectStatusCode specifies the expected HTTP status code of the response.

func FatalFailure

func FatalFailure(parentContext *testing.T) TestOption

FatalFailure will make this fatally fail in the given test context.

func GrabJSONResponse

func GrabJSONResponse(out interface{}) TestOption

GrabJSONResponse takes a pointer to an object and unmarshals the response into it. Use this for examining data outside of the test.

func WithCookieJar added in v0.2.0

func WithCookieJar(jar *cookiejar.Jar) TestOption

func WithFormInput

func WithFormInput(values url.Values) TestOption

WithInput specifies the form request body data for this test and expects application/x-www-form-urlencoded Content-Type. The header expectation can be overriden with WithHeader.

func WithHeader

func WithHeader(name, value string) TestOption

WithHeader specifies a header to be added to the request for this test.

func WithInput

func WithInput(r io.Reader) TestOption

WithInput specifies the request body data for this test.

func WithJSONInput

func WithJSONInput(input interface{}) TestOption

WithInput specifies the JSON request body data for this test and expects application/json Content-Type. The header expectation can be overriden with WithHeader.

Jump to

Keyboard shortcuts

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