feat: support form request (#8)

Co-authored-by: rick <LinuxSuRen@users.noreply.github.com>
This commit is contained in:
Rick 2023-03-08 17:32:53 +08:00 committed by GitHub
parent d07c7f2a99
commit e1270c748e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 73 additions and 11 deletions

View File

@ -1,6 +1,7 @@
build:
mkdir -p bin
go build -o bin/atest cmd/*.go
rm -rf bin/atest
go build -o bin/atest main.go
copy: build
cp bin/atest /usr/local/bin/

8
go.mod
View File

@ -3,7 +3,11 @@ module github.com/linuxsuren/api-testing
go 1.17
require (
github.com/Masterminds/sprig/v3 v3.2.3
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883
github.com/antonmedv/expr v1.12.1
github.com/h2non/gock v1.2.0
github.com/linuxsuren/unstructured v0.0.1
github.com/spf13/cobra v1.4.0
github.com/stretchr/testify v1.8.2
gopkg.in/yaml.v2 v2.4.0
@ -12,16 +16,12 @@ require (
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
github.com/antonmedv/expr v1.12.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.1.1 // indirect
github.com/h2non/gock v1.2.0 // indirect
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/linuxsuren/unstructured v0.0.1 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect

3
go.sum
View File

@ -35,6 +35,7 @@ github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMK
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -53,9 +54,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=

View File

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"reflect"
@ -50,6 +51,20 @@ func RunTestCase(testcase *testing.TestCase, ctx interface{}) (output interface{
return
}
if len(testcase.Request.Form) > 0 {
if testcase.Request.Header["Content-Type"] == "multipart/form-data" {
multiBody := &bytes.Buffer{}
writer := multipart.NewWriter(multiBody)
for key, val := range testcase.Request.Form {
writer.WriteField(key, val)
}
_ = writer.Close()
requestBody = multiBody
testcase.Request.Header["Content-Type"] = writer.FormDataContentType()
}
}
var request *http.Request
if request, err = http.NewRequest(testcase.Request.Method, testcase.Request.API, requestBody); err != nil {
return
@ -68,8 +83,14 @@ func RunTestCase(testcase *testing.TestCase, ctx interface{}) (output interface{
return
}
var responseBodyData []byte
if responseBodyData, err = io.ReadAll(resp.Body); err != nil {
return
}
if testcase.Expect.StatusCode != 0 {
if err = expectInt(testcase.Name, testcase.Expect.StatusCode, resp.StatusCode); err != nil {
err = fmt.Errorf("error is: %v\n%s", err, string(responseBodyData))
return
}
}
@ -81,10 +102,6 @@ func RunTestCase(testcase *testing.TestCase, ctx interface{}) (output interface{
}
}
var responseBodyData []byte
if responseBodyData, err = io.ReadAll(resp.Body); err != nil {
return
}
if testcase.Expect.Body != "" {
if string(responseBodyData) != strings.TrimSpace(testcase.Expect.Body) {
err = fmt.Errorf("case: %s, got different response body, diff: \n%s", testcase.Name,

View File

@ -6,6 +6,7 @@ import (
"testing"
_ "embed"
"github.com/h2non/gock"
atest "github.com/linuxsuren/api-testing/pkg/testing"
"github.com/stretchr/testify/assert"
@ -314,6 +315,27 @@ func TestTestCase(t *testing.T) {
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "template: api:1:")
},
}, {
name: "form request",
testCase: &atest.TestCase{
Request: atest.Request{
API: "http://localhost/foo",
Method: http.MethodPost,
Header: map[string]string{
"Content-Type": "multipart/form-data",
},
Form: map[string]string{
"key": "value",
},
},
},
prepare: func() {
gock.New("http://localhost").
Post("/foo").Reply(http.StatusOK).BodyString(`{"items":[]}`)
},
verify: func(t *testing.T, output interface{}, err error) {
assert.Nil(t, err)
},
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -27,6 +27,7 @@ type Request struct {
Method string `yaml:"method"`
Query map[string]string `yaml:"query"`
Header map[string]string `yaml:"header"`
Form map[string]string `yaml:"form"`
Body string `yaml:"body"`
BodyFromFile string `yaml:"bodyFromFile"`
}

View File

@ -49,5 +49,15 @@ func (r *Request) Render(ctx interface{}) (err error) {
r.Body = buf.String()
}
}
// template the form
for key, val := range r.Form {
if tpl, err = template.New("form").Funcs(sprig.FuncMap()).Parse(val); err == nil {
buf = new(bytes.Buffer)
if err = tpl.Execute(buf, ctx); err == nil {
r.Form[key] = buf.String()
}
}
}
return
}

View File

@ -92,6 +92,18 @@ func TestRender(t *testing.T) {
},
ctx: TestCase{},
hasErr: true,
}, {
name: "form render",
request: &Request{
Form: map[string]string{
"key": "{{.Name}}",
},
},
ctx: TestCase{Name: "linuxsuren"},
verify: func(t *testing.T, req *Request) {
assert.Equal(t, "linuxsuren", req.Form["key"])
},
hasErr: false,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {