Categorygithub.com/podhmo/go-webtest
modulepackage
0.5.10
Repository: https://github.com/podhmo/go-webtest.git
Documentation: pkg.go.dev

# README

CircleCI

go-webtest

features

examples

full test code is here, the test target handler is defined here

with webtest

import (
	"net/http"
	"testing"

	webtest "github.com/podhmo/go-webtest"
	"github.com/podhmo/go-webtest/jsonequal"
	"github.com/podhmo/go-webtest/tripperware"
	"github.com/podhmo/noerror"
)

func TestWithWebtest(t *testing.T) {
	c := webtest.NewClientFromHandler(http.HandlerFunc(Add))
	var want interface{}
	got, err := c.Post("/",
		webtest.WithJSON(bytes.NewBufferString(`{"values": [1,2,3]}`)),
		webtest.WithTripperware(
			tripperware.ExpectCode(t, 200),
			tripperware.GetExpectedDataFromSnapshot(t, &want),
		),
	)

	noerror.Must(t, err)
	defer func() { noerror.Must(t, got.Close()) }()
	noerror.Should(t,
		jsonequal.ShouldBeSame(
			jsonequal.From(got.JSONData()),
			jsonequal.From(want),
		),
	)
}

with try package (shortcut)

import (
	"net/http"
	"testing"

	webtest "github.com/podhmo/go-webtest"
	"github.com/podhmo/go-webtest/try"
)


func TestWithTry(t *testing.T) {
	c := webtest.NewClientFromHandler(http.HandlerFunc(Add))

	var want interface{}
	try.It{
		Code: 200,
		Want: &want,
		ModifyResponse: func(res webtest.Response) (got interface{}) {
			return res.JSONData()
		},
	}.With(t, c,
		"POST", "/",
		webtest.WithJSON(bytes.NewBufferString(`{"values": [1,2,3]}`)),
	)
}

If modify response is not needed, it is also ok, when the response does not include semi-random value (for example the value of now time).

c := webtest.NewClientFromHandler(http.HandlerFunc(Add))

var want interface{}
try.It{
	Code: 200,
	Want: &want,
}.With(t, c,
	"POST", "/",
	webtest.WithJSON(bytes.NewBufferString(`{"values": [1,2,3]}`)),
)

without-webtest (but snapshot testing)

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"reflect"
	"testing"

	"github.com/podhmo/go-webtest/snapshot"
)

func TestWithoutWebtest(t *testing.T) {
	w := httptest.NewRecorder()
	req := httptest.NewRequest("POST", "/", bytes.NewBufferString(`{"values": [1,2,3]}`))
	req.Header.Set("Content-Type", "application/json")

	Add(w, req)
	res := w.Result()

	if res.StatusCode != 200 {
		b, _ := ioutil.ReadAll(res.Body)
		t.Fatalf("status code, want 200, but got %d\n response:%s", res.StatusCode, string(b))
	}

	var got interface{}
	decoder := json.NewDecoder(res.Body)
	if err := decoder.Decode(&got); err != nil {
		t.Fatal(err)
	}
	defer res.Body.Close()

	want := snapshot.Take(t, &got)
	if !reflect.DeepEqual(want, got) {
		t.Errorf(`want %s, but got %s`, want, got)
	}
}

the location of snapshot data

The snapshot data is saved in testdata/<test function name>.golden (e.g. testdata/TestHandler/try.golden) .

{
  "modifiedAt": "2019-09-07T21:40:30.70331035+09:00",
  "data": {
    "request": {
      "method": "POST",
      "path": "/"
    },
    "response": {
      "data": {
        "result": 6
      },
      "statusCode": 200
    }
  }
}

example output if tests are failed

Output examples.

✅ debug trace (not failed)

$ DEBUG=1 go test -v
2019/09/08 08:42:56 builtin debug trace is activated
=== RUN   TestHandler
=== RUN   TestHandler/plain
=== RUN   TestHandler/webtest
	Request : ------------------------------
	POST / HTTP/1.1
	Host: example.com
	Content-Type: application/json
	
	{"values": [1,2,3]}
	----------------------------------------
	Response: ------------------------------
	HTTP/1.1 200 OK
	Connection: close
	Content-Type: application/json
	
	{"result":6}
	----------------------------------------
=== RUN   TestHandler/try
	Request : ------------------------------
	POST / HTTP/1.1
	Host: example.com
	Content-Type: application/json
	
	{"values": [1,2,3]}
	----------------------------------------
	Response: ------------------------------
	HTTP/1.1 200 OK
	Connection: close
	Content-Type: application/json
	
	{"result":6}
	----------------------------------------
--- PASS: TestHandler (0.00s)
    --- PASS: TestHandler/plain (0.00s)
        snapshot.go:56: load snapshot data: "testdata/TestHandler/plain.golden"
    --- PASS: TestHandler/webtest (0.00s)
        snapshot.go:56: load snapshot data: "testdata/TestHandler/webtest.golden"
    --- PASS: TestHandler/try (0.00s)
        snapshot.go:56: load snapshot data: "testdata/TestHandler/try.golden"
PASS
ok  	github.com/podhmo/go-webtest	0.005s

❌ unexpected status

$ go test
--- FAIL: TestHandler (0.00s)
    --- FAIL: TestHandler/try (0.00s)
        snapshot.go:56: load snapshot data: "testdata/TestHandler/try.golden"
        integration_test.go:103: unexpected error, status code, got is "200 OK", but want is "201 Created"
            Response: ------------------------------
            HTTP/1.1 200 OK
            Connection: close
            Content-Type: application/json
            
            {"result":6}
            ----------------------------------------
            
FAIL

❌ unexpected response

$ go test
--- FAIL: TestHandler (0.00s)
    --- FAIL: TestHandler/try (0.00s)
        snapshot.go:56: load snapshot data: "testdata/TestHandler/try.golden"
        integration_test.go:105: on equal check: jsondiff, got and want is not same. (status=NoMatch)
            {
                "result": 10 => 6
            }
            
            left (got) :
            	{"result":10}
            right (want) :
            	{"result":6}
            
FAIL

sub packages

try

todo

snapshot

todo

snapshot/replace

todo

jsonequal

todo

testclient

todo

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Functions

MustParseQuery :.
NewClientFromHandler :.
NewClientFromTestServer :.
NewClientFromURL :.
NewConfig :.
WithBasePath set base path.
WithForm setup as send form-data request.
WithJSON setup as json request.
WithModifyRequest adds request modifyRequest.
WithQuery :.
WithTripperware with client side middleware for roundTripper.

# Structs

Client :.
Config :.

# Interfaces

Internal :.
Option :.

# Type aliases

Response :.