From 8b8195ace1d1a8d9fd8466045b82500716e1c803 Mon Sep 17 00:00:00 2001 From: caixw Date: Thu, 11 Aug 2022 23:51:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=9C=B0=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E5=8C=96=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/go.yml | 2 +- .gitignore | 6 +- assert.go | 108 ++++++++++++++++++++++++++++------- assert_test.go | 42 ++++++++++++++ assertion.go | 119 ++++++++++++++++++--------------------- rest/response.go | 27 +++++---- rest/rest.go | 11 ++-- rest/rest_test.go | 6 +- 8 files changed, 211 insertions(+), 110 deletions(-) create mode 100644 assert_test.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f4e9f43..6b9ee3d 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,7 +10,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macOS-latest, windows-latest] - go: ['1.17.x', '1.18.x'] + go: ['1.17.x', '1.19.x'] steps: diff --git a/.gitignore b/.gitignore index 8c78227..dd2228c 100644 --- a/.gitignore +++ b/.gitignore @@ -23,11 +23,11 @@ _testmain.go *.test *.prof -# vim -*.swp - # osx .DS_Store +# ide .vscode .idea +.vs +*.swp diff --git a/assert.go b/assert.go index bf3faa5..e3ece31 100644 --- a/assert.go +++ b/assert.go @@ -2,25 +2,95 @@ // Package assert 是对 testing 包的一些简单包装 // -// func TestAssert(t *testing.T) { -// var v interface{} = 5 +// func TestAssert(t *testing.T) { +// var v interface{} = 5 // -// a := assert.New(t, false) -// a.True(v==5, "v的值[%v]不等于5", v). -// Equal(5, v, "v的值[%v]不等于5", v). -// Nil(v). -// TB().Log("success") +// a := assert.New(t, false) +// a.True(v==5, "v的值[%v]不等于5", v). +// Equal(5, v, "v的值[%v]不等于5", v). +// Nil(v). +// TB().Log("success") +// } // -// // 以函数链的形式调用 Assertion 对象的方法 -// a.True(false).Equal(5,6) -// } -// -// // 也可以对 testing.B 使用 -// func Benchmark1(b *testing.B) { -// a := assert.New(b) -// a.True(false) -// for(i:=0; i 0 { + keys := make([]string, 0, len(f.Values)) + for k := range f.Values { + keys = append(keys, k) + } + sort.Strings(keys) + + s.WriteString("反馈以下参数:\n") + for _, k := range keys { + s.WriteString(k) + s.WriteByte('=') + s.WriteString(fmt.Sprint(f.Values[k])) + s.WriteByte('\n') + } + } + + if f.User != "" { + s.WriteString("用户反馈信息:") + s.WriteString(f.User) + } + + return s.String() +} + +func NewFailure(action string, user []interface{}, kv map[string]interface{}) *Failure { + var u string + if len(user) > 0 { + switch v := user[0].(type) { + case string: + u = fmt.Sprintf(v, user[1:]...) + default: + u = fmt.Sprint(user...) + } + } + + return &Failure{ + Action: action, + User: u, + Values: kv, + } +} diff --git a/assert_test.go b/assert_test.go new file mode 100644 index 0000000..f12c428 --- /dev/null +++ b/assert_test.go @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT + +package assert + +import "testing" + +func TestDefaultFailureSprint(t *testing.T) { + f := NewFailure("A", nil, nil) + if f.Action != "A" || f.User != "" || len(f.Values) != 0 { + t.Error("err1") + } + if s := DefaultFailureSprint(f); s != "A 断言失败!" { + t.Error("err2") + } + + // 带 user + f = NewFailure("AB", []interface{}{1, 2}, nil) + if f.Action != "AB" || f.User != "1 2" || len(f.Values) != 0 { + t.Error("err3") + } + if s := DefaultFailureSprint(f); s != "AB 断言失败!用户反馈信息:1 2" { + t.Error("err4", s) + } + + // 带 values + f = NewFailure("AB", nil, map[string]interface{}{"k1": "v1", "k2": 2}) + if f.Action != "AB" || f.User != "" || len(f.Values) != 2 { + t.Error("err5") + } + if s := DefaultFailureSprint(f); s != "AB 断言失败!反馈以下参数:\nk1=v1\nk2=2\n" { + t.Error("err6", s) + } + + // 带 user,values + f = NewFailure("AB", []interface{}{1, 2}, map[string]interface{}{"k1": "v1", "k2": 2}) + if f.Action != "AB" || f.User == "" || len(f.Values) != 2 { + t.Error("err7") + } + if s := DefaultFailureSprint(f); s != "AB 断言失败!反馈以下参数:\nk1=v1\nk2=2\n用户反馈信息:1 2" { + t.Error("err8", s) + } +} diff --git a/assertion.go b/assertion.go index 984dea4..327ee04 100644 --- a/assertion.go +++ b/assertion.go @@ -19,6 +19,7 @@ type Assertion struct { fatal bool print func(...interface{}) printf func(string, ...interface{}) + f FailureSprintFunc runner runner } @@ -40,12 +41,13 @@ func New(tb testing.TB, fatal bool) *Assertion { fatal: fatal, print: p, printf: pf, + f: failureSprint, } } // NewWithEnv 以指定的环境变量初始化 *Assertion 对象 // -// 最后会以 t.Setenv 的形式调用。 +// env 是以 t.Setenv 的形式调用。 func NewWithEnv(tb testing.TB, fatal bool, env map[string]string) *Assertion { for k, v := range env { tb.Setenv(k, v) @@ -55,84 +57,65 @@ func NewWithEnv(tb testing.TB, fatal bool, env map[string]string) *Assertion { // Assert 断言 expr 条件成立 // -// msg1,msg2 输出的错误信息,优先使用 msg1 中的信息,若不存在,则使用 msg2 的内容。 -// msg1 和 msg2 格式完全相同,根据其每一个元素是否为 string 决定是调用 Error 还是 Errorf。 +// f 表示在断言失败时输出的信息 // // 普通用户直接使用 True 效果是一样的, // 之所以提供该函数,主要供库调用,可以提供一个默认的错误信息。 -func (a *Assertion) Assert(expr bool, msg1, msg2 []interface{}) *Assertion { +func (a *Assertion) Assert(expr bool, f *Failure) *Assertion { if expr { return a } a.TB().Helper() - - if len(msg1) == 0 { - msg1 = msg2 - } - if len(msg1) == 0 { - panic("未提供任何错误信息") - } - - if len(msg1) == 1 { - a.print(msg1...) - return a - } - - if format, ok := msg1[0].(string); ok { - a.printf(format, msg1[1:]...) - } else { - a.print(msg1...) - } - + a.print(a.f(f)) return a } -// TB 返回 testing.TB 接口 +// TB 返回 [testing.TB] 接口 func (a *Assertion) TB() testing.TB { return a.tb } -// True 断言表达式 expr 为 true +// True 断言表达式 expr 为真 // // args 对应 fmt.Printf() 函数中的参数,其中 args[0] 对应第一个参数 format,依次类推, // 具体可参数 Assert 方法的介绍。其它断言函数的 args 参数,功能与此相同。 func (a *Assertion) True(expr bool, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(expr, msg, []interface{}{"True 失败"}) + return a.Assert(expr, NewFailure("True", msg, nil)) } func (a *Assertion) False(expr bool, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(!expr, msg, []interface{}{"False 失败"}) + return a.Assert(!expr, NewFailure("False", msg, nil)) } func (a *Assertion) Nil(expr interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(isNil(expr), msg, []interface{}{"Nil 失败,实际值为 %#v", expr}) + return a.Assert(isNil(expr), NewFailure("Nil", msg, map[string]interface{}{"v": expr})) } func (a *Assertion) NotNil(expr interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(!isNil(expr), msg, []interface{}{"NotNil 失败,实际值为 %#v", expr}) + return a.Assert(!isNil(expr), NewFailure("NotNil", msg, map[string]interface{}{"v": expr})) } func (a *Assertion) Equal(v1, v2 interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(isEqual(v1, v2), msg, []interface{}{"Equal 失败,实际值为\nv1=%#v\nv2=%#v", v1, v2}) + return a.Assert(isEqual(v1, v2), NewFailure("Equal", msg, map[string]interface{}{"v1": v1, "v2": v2})) } func (a *Assertion) NotEqual(v1, v2 interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(!isEqual(v1, v2), msg, []interface{}{"NotEqual 失败,实际值为\nv1=%#v\nv2=%#v", v1, v2}) + return a.Assert(!isEqual(v1, v2), NewFailure("NotEqual", msg, map[string]interface{}{"v1": v1, "v2": v2})) } func (a *Assertion) Empty(expr interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(isEmpty(expr), msg, []interface{}{"Empty 失败,实际值为 %#v", expr}) + return a.Assert(isEmpty(expr), NewFailure("Empty", msg, map[string]interface{}{"v": expr})) } func (a *Assertion) NotEmpty(expr interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(!isEmpty(expr), msg, []interface{}{"NotEmpty 失败,实际值为 %#v", expr}) + return a.Assert(!isEmpty(expr), NewFailure("NotEmpty", msg, map[string]interface{}{"v": expr})) } // Error 断言有错误发生 @@ -142,7 +125,7 @@ func (a *Assertion) NotEmpty(expr interface{}, msg ...interface{}) *Assertion { // NotNil 的特化版本,限定了类型为 error。 func (a *Assertion) Error(expr error, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(!isNil(expr), msg, []interface{}{"Error 失败,实际值为 Nil:%T", expr}) + return a.Assert(!isNil(expr), NewFailure("Error", msg, map[string]interface{}{"v": expr})) } // ErrorString 断言有错误发生且错误信息中包含指定的字符串 str @@ -152,9 +135,9 @@ func (a *Assertion) ErrorString(expr error, str string, msg ...interface{}) *Ass a.TB().Helper() if isNil(expr) { // 空值,必定没有错误 - return a.Assert(false, msg, []interface{}{"ErrorString 失败,实际值为 Nil:%T", expr}) + return a.Assert(false, NewFailure("ErrorString", msg, map[string]interface{}{"v": expr})) } - return a.Assert(strings.Contains(expr.Error(), str), msg, []interface{}{"ErrorString 失败,当前值为 %s", expr.Error()}) + return a.Assert(strings.Contains(expr.Error(), str), NewFailure("ErrorString", msg, map[string]interface{}{"v": expr})) } // ErrorIs 断言 expr 为 target 类型 @@ -162,7 +145,7 @@ func (a *Assertion) ErrorString(expr error, str string, msg ...interface{}) *Ass // 相当于 a.True(errors.Is(expr, target)) func (a *Assertion) ErrorIs(expr, target error, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(errors.Is(expr, target), msg, []interface{}{"ErrorIs 失败,expr 不是且不包含 target。"}) + return a.Assert(errors.Is(expr, target), NewFailure("ErrorIs", msg, nil)) } // NotError 断言没有错误 @@ -170,14 +153,14 @@ func (a *Assertion) ErrorIs(expr, target error, msg ...interface{}) *Assertion { // Nil 的特化版本,限定了类型为 error。 func (a *Assertion) NotError(expr error, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(isNil(expr), msg, []interface{}{"NotError 失败,实际值为:%s", expr}) + return a.Assert(isNil(expr), NewFailure("NotError", msg, map[string]interface{}{"v": expr})) } func (a *Assertion) FileExists(path string, msg ...interface{}) *Assertion { a.TB().Helper() if _, err := os.Stat(path); err != nil && !errors.Is(err, fs.ErrExist) { - return a.Assert(false, msg, []interface{}{"FileExists 失败,且附带以下错误:%v", err}) + return a.Assert(false, NewFailure("FileExists", msg, map[string]interface{}{"err": err})) } return a } @@ -187,10 +170,10 @@ func (a *Assertion) FileNotExists(path string, msg ...interface{}) *Assertion { _, err := os.Stat(path) if err == nil { - return a.Assert(false, msg, []interface{}{"FileNotExists 失败"}) + return a.Assert(false, NewFailure("FileNotExists", msg, nil)) } if errors.Is(err, fs.ErrExist) { - return a.Assert(false, msg, []interface{}{"FileNotExists 失败,且返回以下错误信息:%v", err}) + return a.Assert(false, NewFailure("FileNotExists", msg, map[string]interface{}{"err": err})) } return a @@ -200,7 +183,7 @@ func (a *Assertion) FileExistsFS(fsys fs.FS, path string, msg ...interface{}) *A a.TB().Helper() if _, err := fs.Stat(fsys, path); err != nil && !errors.Is(err, fs.ErrExist) { - return a.Assert(false, msg, []interface{}{"FileExistsFS 失败,且附带以下错误:%v", err}) + return a.Assert(false, NewFailure("FileExistsFS", msg, map[string]interface{}{"err": err})) } return a @@ -211,10 +194,10 @@ func (a *Assertion) FileNotExistsFS(fsys fs.FS, path string, msg ...interface{}) _, err := fs.Stat(fsys, path) if err == nil { - return a.Assert(false, msg, []interface{}{"FileNotExistsFS 失败"}) + return a.Assert(false, NewFailure("FileNotExistsFS", msg, nil)) } if errors.Is(err, fs.ErrExist) { - return a.Assert(false, msg, []interface{}{"FileNotExistsFS 失败,且返回以下错误信息:%v", err}) + return a.Assert(false, NewFailure("FileNotExistsFS", msg, map[string]interface{}{"err": err})) } return a @@ -224,7 +207,7 @@ func (a *Assertion) Panic(fn func(), msg ...interface{}) *Assertion { a.TB().Helper() has, _ := hasPanic(fn) - return a.Assert(has, msg, []interface{}{"并未发生 panic"}) + return a.Assert(has, NewFailure("Panic", msg, nil)) } // PanicString 断言函数会发生 panic 且 panic 信息中包含指定的字符串内容 @@ -232,9 +215,9 @@ func (a *Assertion) PanicString(fn func(), str string, msg ...interface{}) *Asse a.TB().Helper() if has, m := hasPanic(fn); has { - return a.Assert(strings.Contains(fmt.Sprint(m), str), msg, []interface{}{"panic 中并未包含 %s", str}) + return a.Assert(strings.Contains(fmt.Sprint(m), str), NewFailure("PanicString", msg, map[string]interface{}{"err": str})) } - return a.Assert(false, msg, []interface{}{"并未发生 panic"}) + return a.Assert(false, NewFailure("PanicString", msg, nil)) } // PanicType 断言函数会发生 panic 且抛出指定的类型 @@ -243,19 +226,19 @@ func (a *Assertion) PanicType(fn func(), typ interface{}, msg ...interface{}) *A if has, m := hasPanic(fn); has { t1, t2 := getType(true, m, typ) - return a.Assert(t1 == t2, msg, []interface{}{"PanicType 失败,v1[%v] 的类型与 v2[%v] 的类型不相同", t1, t2}) + return a.Assert(t1 == t2, NewFailure("PanicType", msg, map[string]interface{}{"v1": t1, "v2": t2})) } - return a.Assert(false, msg, []interface{}{"并未发生 panic"}) + return a.Assert(false, NewFailure("PanicType", msg, nil)) } func (a *Assertion) NotPanic(fn func(), msg ...interface{}) *Assertion { a.TB().Helper() has, m := hasPanic(fn) - return a.Assert(!has, msg, []interface{}{"发生了 panic,其信息为 %v", m}) + return a.Assert(!has, NewFailure("NotPanic", msg, map[string]interface{}{"err": m})) } -// Contains 断言 container 包含 item 的或是包含 item 中的所有项 +// Contains 断言 container 包含 item 或是包含 item 中的所有项 // // 若 container 是字符串(string、[]byte 和 []rune,不包含 fmt.Stringer 接口), // 都将会以字符串的形式判断其是否包含 item。 @@ -263,13 +246,13 @@ func (a *Assertion) NotPanic(fn func(), msg ...interface{}) *Assertion { // 的所有项,或是 item 本身就是 container 中的一个元素。 func (a *Assertion) Contains(container, item interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(isContains(container, item), msg, []interface{}{"Contains 失败,%v 并未包含 %v", container, item}) + return a.Assert(isContains(container, item), NewFailure("Contains", msg, map[string]interface{}{"container": container, "item": item})) } -// NotContains 断言 container 不包含 item 的或是不包含 item 中的所有项 +// NotContains 断言 container 不包含 item 或是不包含 item 中的所有项 func (a *Assertion) NotContains(container, item interface{}, msg ...interface{}) *Assertion { a.TB().Helper() - return a.Assert(!isContains(container, item), msg, []interface{}{"NotContains 失败,%v 包含 %v", container, item}) + return a.Assert(!isContains(container, item), NewFailure("NotContains", msg, map[string]interface{}{"container": container, "item": item})) } // Zero 断言是否为零值 @@ -279,7 +262,7 @@ func (a *Assertion) Zero(v interface{}, msg ...interface{}) *Assertion { a.TB().Helper() isZero := v == nil || reflect.ValueOf(v).IsZero() - return a.Assert(isZero, msg, []interface{}{"%#v 为非零值", v}) + return a.Assert(isZero, NewFailure("Zero", msg, map[string]interface{}{"v": v})) } // NotZero 断言是否为非零值 @@ -289,38 +272,46 @@ func (a *Assertion) NotZero(v interface{}, msg ...interface{}) *Assertion { a.TB().Helper() isZero := v == nil || reflect.ValueOf(v).IsZero() - return a.Assert(!isZero, msg, []interface{}{"%#v 为零值", v}) + return a.Assert(!isZero, NewFailure("NotZero", msg, map[string]interface{}{"v": v})) } // Length 断言长度是否为指定的值 // -// v 可以是 map,string,slice,array +// v 可以是以下类型: +// - map +// - string +// - slice +// - array func (a *Assertion) Length(v interface{}, l int, msg ...interface{}) *Assertion { a.TB().Helper() rl, err := getLen(v) if err != "" { - a.Assert(false, msg, []interface{}{err}) + a.Assert(false, NewFailure("Length", msg, map[string]interface{}{"err": err})) } - return a.Assert(rl == l, msg, []interface{}{"并非预期的长度,元素长度:%d, 期望的长度:%d", rl, l}) + return a.Assert(rl == l, NewFailure("Length", msg, map[string]interface{}{"l1": rl, "l2": l})) } // NotLength 断言长度不是指定的值 // -// v 可以是 map,string,slice,array +// v 可以是以下类型: +// - map +// - string +// - slice +// - array func (a *Assertion) NotLength(v interface{}, l int, msg ...interface{}) *Assertion { a.TB().Helper() rl, err := getLen(v) if err != "" { - a.Assert(false, msg, []interface{}{err}) + a.Assert(false, NewFailure("NotLength", msg, map[string]interface{}{"err": err})) } - return a.Assert(rl != l, msg, []interface{}{"长度均为 %d", rl}) + return a.Assert(rl != l, NewFailure("NotLength", msg, map[string]interface{}{"l": rl})) } // TypeEqual 断言两个值的类型是否相同 // -// ptr 如果为 true,则会在对象为指定时,查找其指向的对象。 +// ptr 如果为 true,则会在对象为指针时,查找其指向的对象。 func (a *Assertion) TypeEqual(ptr bool, v1, v2 interface{}, msg ...interface{}) *Assertion { if v1 == v2 { return a @@ -329,5 +320,5 @@ func (a *Assertion) TypeEqual(ptr bool, v1, v2 interface{}, msg ...interface{}) a.TB().Helper() t1, t2 := getType(ptr, v1, v2) - return a.Assert(t1 == t2, msg, []interface{}{"TypeEqual 失败,v1: %v,v2: %v", t1, t2}) + return a.Assert(t1 == t2, NewFailure("TypeEquaal", msg, map[string]interface{}{"v1": t1, "v2": t2})) } diff --git a/rest/response.go b/rest/response.go index 4c536f7..8232cd5 100644 --- a/rest/response.go +++ b/rest/response.go @@ -8,7 +8,6 @@ import ( "encoding/xml" "errors" "io" - "io/ioutil" "net/http" "net/http/httptest" "reflect" @@ -47,7 +46,7 @@ func (req *Request) Do(h http.Handler) *Response { var bs []byte if resp.Body != nil { - bs, err = ioutil.ReadAll(resp.Body) + bs, err = io.ReadAll(resp.Body) if err != io.EOF { req.a.NotError(err) } @@ -66,9 +65,9 @@ func (req *Request) Do(h http.Handler) *Response { // NOTE: http.Response.Body 内容已经被读取且关闭。 func (resp *Response) Resp() *http.Response { return resp.resp } -func (resp *Response) assert(expr bool, msg1, msg2 []interface{}) *Response { +func (resp *Response) assert(expr bool, f *assert.Failure) *Response { resp.a.TB().Helper() - resp.a.Assert(expr, msg1, msg2) + resp.a.Assert(expr, f) return resp } @@ -76,28 +75,28 @@ func (resp *Response) assert(expr bool, msg1, msg2 []interface{}) *Response { func (resp *Response) Success(msg ...interface{}) *Response { resp.a.TB().Helper() succ := resp.resp.StatusCode >= 100 && resp.resp.StatusCode < 400 - return resp.assert(succ, msg, []interface{}{"当前状态码为 %d", resp.resp.StatusCode}) + return resp.assert(succ, assert.NewFailure("Success", msg, map[string]interface{}{"status": resp.resp.StatusCode})) } // Fail 状态码是否大于 399 func (resp *Response) Fail(msg ...interface{}) *Response { resp.a.TB().Helper() fail := resp.resp.StatusCode >= 400 - return resp.assert(fail, msg, []interface{}{"当前状态为 %d", resp.resp.StatusCode}) + return resp.assert(fail, assert.NewFailure("Fail", msg, map[string]interface{}{"status": resp.resp.StatusCode})) } // Status 判断状态码是否与 status 相等 func (resp *Response) Status(status int, msg ...interface{}) *Response { resp.a.TB().Helper() eq := resp.resp.StatusCode == status - return resp.assert(eq, msg, []interface{}{"实际状态为 %d,与期望值 %d 不符合", resp.resp.StatusCode, status}) + return resp.assert(eq, assert.NewFailure("Status", msg, map[string]interface{}{"status1": resp.resp.StatusCode, "status2": status})) } // NotStatus 判断状态码是否与 status 不相等 func (resp *Response) NotStatus(status int, msg ...interface{}) *Response { resp.a.TB().Helper() neq := resp.resp.StatusCode != status - return resp.assert(neq, msg, []interface{}{"状态码 %d 与期望值是相同的", resp.resp.StatusCode}) + return resp.assert(neq, assert.NewFailure("NotStatus", msg, map[string]interface{}{"status": resp.resp.StatusCode})) } // Header 判断指定的报头是否与 val 相同 @@ -106,39 +105,39 @@ func (resp *Response) NotStatus(status int, msg ...interface{}) *Response { func (resp *Response) Header(key string, val string, msg ...interface{}) *Response { resp.a.TB().Helper() h := resp.resp.Header.Get(key) - return resp.assert(h == val, msg, []interface{}{"报头 %s 的值 %s 与期望值 %s 不同", key, h, val}) + return resp.assert(h == val, assert.NewFailure("Header", msg, map[string]interface{}{"header": key, "v1": h, "v2": val})) } // NotHeader 指定的报头必定不与 val 相同。 func (resp *Response) NotHeader(key string, val string, msg ...interface{}) *Response { resp.a.TB().Helper() h := resp.resp.Header.Get(key) - return resp.assert(h != val, msg, []interface{}{"报头 %s 与期望值 %s 相等", key, h}) + return resp.assert(h != val, assert.NewFailure("NotHeader", msg, map[string]interface{}{"header": key, "v": h})) } // Body 断言内容与 val 相同 func (resp *Response) Body(val []byte, msg ...interface{}) *Response { resp.a.TB().Helper() - return resp.assert(bytes.Equal(resp.body, val), msg, []interface{}{"内容并不相同:\nv1=%s\nv2=%s", string(resp.body), string(val)}) + return resp.assert(bytes.Equal(resp.body, val), assert.NewFailure("Body", msg, map[string]interface{}{"v1": string(resp.body), "v2": string(val)})) } // StringBody 断言内容与 val 相同 func (resp *Response) StringBody(val string, msg ...interface{}) *Response { resp.a.TB().Helper() b := string(resp.body) - return resp.assert(b == val, msg, []interface{}{"内容并不相同:\nv1=%s\nv2=%s", b, val}) + return resp.assert(b == val, assert.NewFailure("StringBody", msg, map[string]interface{}{"v1": b, "v2": val})) } // BodyNotEmpty 报文内容是否不为空 func (resp *Response) BodyNotEmpty(msg ...interface{}) *Response { resp.a.TB().Helper() - return resp.assert(len(resp.body) > 0, msg, []interface{}{"内容为空"}) + return resp.assert(len(resp.body) > 0, assert.NewFailure("BodyNotEmpty", msg, nil)) } // BodyEmpty 报文内容是否为空 func (resp *Response) BodyEmpty(msg ...interface{}) *Response { resp.a.TB().Helper() - return resp.assert(len(resp.body) == 0, msg, []interface{}{"内容并不为空:%s", string(resp.body)}) + return resp.assert(len(resp.body) == 0, assert.NewFailure("BodyEmpty", msg, map[string]interface{}{"v": resp.body})) } // JSONBody body 转换成 JSON 对象之后是否等价于 val diff --git a/rest/rest.go b/rest/rest.go index a1a5e63..2431ff8 100644 --- a/rest/rest.go +++ b/rest/rest.go @@ -7,7 +7,6 @@ import ( "bufio" "bytes" "io" - "io/ioutil" "net/http" "net/http/httptest" "net/url" @@ -18,9 +17,9 @@ import ( // BuildHandler 生成用于测试的 http.Handler 对象 // // 仅是简单地按以下步骤输出内容: -// - 输出状态码 code; -// - 输出报头 headers,以 Add 方式,而不是 set,不会覆盖原来的数据; -// - 输出 body,如果为空字符串,则不会输出; +// - 输出状态码 code; +// - 输出报头 headers,以 Add 方式,而不是 set,不会覆盖原来的数据; +// - 输出 body,如果为空字符串,则不会输出; func BuildHandler(a *assert.Assertion, code int, body string, headers map[string]string) http.Handler { return http.HandlerFunc(BuildHandlerFunc(a, code, body, headers)) } @@ -116,9 +115,9 @@ func compare(a *assert.Assertion, resp *http.Response, status int, header http.H a.Equal(respV, retV, "compare 断言失败,报头 %s 的期望值 %s 与实际值 %s 不相同", k, respV, retV) } - retB, err := ioutil.ReadAll(body) + retB, err := io.ReadAll(body) a.NotError(err).NotNil(retB) - respB, err := ioutil.ReadAll(resp.Body) + respB, err := io.ReadAll(resp.Body) a.NotError(err).NotNil(respB) retB = bytes.TrimSpace(retB) respB = bytes.TrimSpace(respB) diff --git a/rest/rest_test.go b/rest/rest_test.go index 055292a..f2c2626 100644 --- a/rest/rest_test.go +++ b/rest/rest_test.go @@ -6,7 +6,7 @@ import ( "encoding/json" "encoding/xml" "fmt" - "io/ioutil" + "io" "net/http" "net/http/httptest" "strings" @@ -29,7 +29,7 @@ var h = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/body" { if r.Header.Get("content-type") == "application/json" { b := &bodyTest{} - bs, err := ioutil.ReadAll(r.Body) + bs, err := io.ReadAll(r.Body) if err != nil { fmt.Println(err) w.WriteHeader(http.StatusInternalServerError) @@ -57,7 +57,7 @@ var h = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("content-type") == "application/xml" { b := &bodyTest{} - bs, err := ioutil.ReadAll(r.Body) + bs, err := io.ReadAll(r.Body) if err != nil { fmt.Println(err) w.WriteHeader(http.StatusInternalServerError)