From 619fb6eaa72487eaa0295f1ad5a39cf3659dd110 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Fri, 11 Feb 2022 15:10:37 +0800 Subject: [PATCH 01/11] fix: json number convert rule Change-Id: I68a811b803631ef78b6b12fe548f98b676a10eb3 --- parser.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/parser.go b/parser.go index ce2a8fe3..692faf75 100644 --- a/parser.go +++ b/parser.go @@ -69,7 +69,8 @@ func (p *parser) parseData(raw interface{}, variablesMapping map[string]interfac case reflect.String: // json.Number if rawValue, ok := raw.(json.Number); ok { - return parseJSONNumber(rawValue) + // use the same rule as json.Unmarshal (float64, for JSON numbers) + return rawValue.Float64() } // other string value := rawValue.String() @@ -108,16 +109,6 @@ func (p *parser) parseData(raw interface{}, variablesMapping map[string]interfac } } -func parseJSONNumber(raw json.Number) (interface{}, error) { - if strings.Contains(raw.String(), ".") { - // float64 - return raw.Float64() - } else { - // int64 - return raw.Int64() - } -} - const ( regexVariable = `[a-zA-Z_]\w*` // variable name should start with a letter or underscore regexFunctionName = `[a-zA-Z_]\w*` // function name should start with a letter or underscore From fbeecc2693349fbddf78b13f579bb29eb7747b01 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Fri, 11 Feb 2022 15:11:37 +0800 Subject: [PATCH 02/11] fix: incorrect assertion func Change-Id: I66f25fcf00e36e83308e820b859b4a94907833fc --- internal/builtin/assertion.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/builtin/assertion.go b/internal/builtin/assertion.go index 6acb06ed..189347c2 100644 --- a/internal/builtin/assertion.go +++ b/internal/builtin/assertion.go @@ -11,10 +11,10 @@ import ( var Assertions = map[string]func(t assert.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool{ "equals": assert.EqualValues, "equal": assert.EqualValues, // alias for equals - "greater_than": assert.Greater, - "less_than": assert.Less, - "greater_or_equals": assert.GreaterOrEqual, - "less_or_equals": assert.LessOrEqual, + "greater_than": assert.Less, + "less_than": assert.Greater, + "greater_or_equals": assert.LessOrEqual, + "less_or_equals": assert.GreaterOrEqual, "not_equal": assert.NotEqual, "contained_by": assert.Contains, "regex_match": assert.Regexp, From 293551997f1945aa19b7cca154bb92c7c7268958 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Fri, 11 Feb 2022 15:20:31 +0800 Subject: [PATCH 03/11] add httpbingo test Change-Id: I41911d2a723ac64d5aa0cdf6b3f99b2554c6a196 --- examples/httpbingo_test.json | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 examples/httpbingo_test.json diff --git a/examples/httpbingo_test.json b/examples/httpbingo_test.json new file mode 100644 index 00000000..b3461ee4 --- /dev/null +++ b/examples/httpbingo_test.json @@ -0,0 +1,32 @@ +{ + "config": { + "name": "request methods testcase: validate with parameters", + "base_url": "https://httpbingo.bytedance.net" + }, + "teststeps": [ + { + "name": "get with params", + "request": { + "method": "GET", + "url": "/get", + "params": { + "a": 1 + } + }, + "validate": [ + { + "check": "status_code", + "assert": "greater_than", + "expect": 199, + "msg": "check status code" + }, + { + "check": "body.args.a", + "assert": "equal", + "expect": "1", + "msg": "check argument a" + } + ] + } + ] +} \ No newline at end of file From 5c03e0d3254bd3be3c9c1c327a1923f9db95d7e0 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Fri, 11 Feb 2022 17:54:32 +0800 Subject: [PATCH 04/11] modify assertion functions and their docs Change-Id: I12bc6425e098b62b08bd5ca2fb7a9cc0482e1910 --- docs/BUILTIN.md | 28 +++++---- docs/CHANGELOG.md | 4 ++ internal/builtin/assertion.go | 96 ++++++++++++++++++------------ internal/builtin/assertion_test.go | 65 +++++++++++++++++--- response.go | 7 ++- 5 files changed, 142 insertions(+), 58 deletions(-) diff --git a/docs/BUILTIN.md b/docs/BUILTIN.md index 19c6bff5..a4b9305b 100644 --- a/docs/BUILTIN.md +++ b/docs/BUILTIN.md @@ -6,23 +6,27 @@ HttpRunner+ validation should follow the following format. `check`, `assert` and ```json { - "check": "status_code", // target field, usually used with jmespath - "assert": "equals", // assertion method, you can use builtin method or custom defined function - "expect": 200, // expected value - "msg": "check response status code" // optional, print this message if assertion failed + "check": "status_code", + // target field, usually used with jmespath + "assert": "equals", + // assertion method, you can use builtin method or custom defined function + "expect": 200, + // expected value + "msg": "check response status code" + // optional, print this message if assertion failed } ``` The `assert` method name will be mapped to a built-in function with the following function signature. ```go -func(t assert.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool +func(t assert.TestingT, actual interface{}, expected interface{}, msgAndArgs ...interface{}) bool ``` Currently, HttpRunner+ has the following built-in assertion functions. | `assert` | Description | A(check), B(expect) | examples | -| -- | -- | -- | -- | +| --- | --- | --- | --- | | `eq`, `equals`, `equal` | value is equal | A == B | 9 eq 9 | | `lt`, `less_than` | less than | A < B | 7 lt 8 | | `le`, `less_or_equals` | less than or equals | A <= B | 7 le 8, 8 le 8 | @@ -31,16 +35,16 @@ Currently, HttpRunner+ has the following built-in assertion functions. | `ne`, `not_equal` | not equals | A != B | 6 ne 9 | | `str_eq`, `string_equals` | string equals | str(A) == str(B) | 123 str_eq '123' | | `len_eq`, `length_equals`, `length_equal` | length equals | len(A) == B | 'abc' len_eq 3, [1,2] len_eq 2 | -| `len_gt`, `count_gt` | length greater than | len(A) > B | 'abc' len_gt 2, [1,2,3] len_gt 2 | -| `len_ge`, `count_ge` | length greater than or equals | len(A) >= B | 'abc' len_ge 3, [1,2,3] len_gt 3 | -| `len_lt`, `count_lt` | length less than | len(A) < B | 'abc' len_lt 4, [1,2,3] len_lt 4 | -| `len_le`, `count_le` | length less than or equals | len(A) <= B | 'abc' len_le 3, [1,2,3] len_le 3 | +| `len_gt`, `count_gt`, `length_greater_than` | length greater than | len(A) > B | 'abc' len_gt 2, [1,2,3] len_gt 2 | +| `len_ge`, `count_ge`, `length_greater_or_equals` | length greater than or equals | len(A) >= B | 'abc' len_ge 3, [1,2,3] len_gt 3 | +| `len_lt`, `count_lt`, `length_less_than` | length less than | len(A) < B | 'abc' len_lt 4, [1,2,3] len_lt 4 | +| `len_le`, `count_le`, `length_less_or_equals` | length less than or equals | len(A) <= B | 'abc' len_le 3, [1,2,3] len_le 3 | | `contains` | contains | [1, 2] contains 1 | 'abc' contains 'a', [1,2,3] len_lt 4 | | `contained_by` | contained by | A in B | 'a' contained_by 'abc', 1 contained_by [1,2] | | `type_match` | A and B are in the same type | type(A) == type(B) | 123 type_match 1 | | `regex_match` | regex matches | re.match(B, A) | 'abcdef' regex 'a\w+d' | -| `startswith` | starts with | A.startswith(B) is True | 'abc' startswith 'ab' | -| `endswith` | ends with | A.endswith(B) is True | 'abc' endswith 'bc' | +| `starts_with` | starts with | A.startswith(B) is True | 'abc' startswith 'ab' | +| `ends_with` | ends with | A.endswith(B) is True | 'abc' endswith 'bc' | ## Builtin functions diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 66744592..1cada300 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,5 +1,9 @@ # Release History +## v0.6.1 (2022-02-11) + +- fix: assertion function and json number parse rule + ## v0.6.0 (2022-02-08) - feat: implement `rendezvous` mechanism for data driven diff --git a/internal/builtin/assertion.go b/internal/builtin/assertion.go index 189347c2..d7de8482 100644 --- a/internal/builtin/assertion.go +++ b/internal/builtin/assertion.go @@ -8,31 +8,48 @@ import ( "github.com/stretchr/testify/assert" ) -var Assertions = map[string]func(t assert.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool{ +var Assertions = map[string]func(t assert.TestingT, actual interface{}, expected interface{}, msgAndArgs ...interface{}) bool{ + "eq": assert.EqualValues, "equals": assert.EqualValues, - "equal": assert.EqualValues, // alias for equals - "greater_than": assert.Less, - "less_than": assert.Greater, - "greater_or_equals": assert.LessOrEqual, - "less_or_equals": assert.GreaterOrEqual, + "equal": assert.EqualValues, + "lt": assert.Less, + "less_than": assert.Less, + "le": assert.LessOrEqual, + "less_or_equals": assert.LessOrEqual, + "gt": assert.Greater, + "greater_than": assert.Greater, + "ge": assert.GreaterOrEqual, + "greater_or_equals": assert.GreaterOrEqual, + "ne": assert.NotEqual, "not_equal": assert.NotEqual, - "contained_by": assert.Contains, - "regex_match": assert.Regexp, + "contains": assert.Contains, "type_match": assert.IsType, // custom assertions - "startswith": StartsWith, // check if string starts with substring - "endswith": EndsWith, // check if string ends with substring + "starts_with": StartsWith, + "ends_with": EndsWith, + "len_eq": EqualLength, "length_equals": EqualLength, - "length_equal": EqualLength, // alias for length_equals + "length_equal": EqualLength, + "len_lt": LessThanLength, + "count_lt": LessThanLength, "length_less_than": LessThanLength, + "len_le": LessOrEqualsLength, + "count_le": LessOrEqualsLength, "length_less_or_equals": LessOrEqualsLength, + "len_gt": GreaterThanLength, + "count_gt": GreaterThanLength, "length_greater_than": GreaterThanLength, + "len_ge": GreaterOrEqualsLength, + "count_ge": GreaterOrEqualsLength, "length_greater_or_equals": GreaterOrEqualsLength, - "contains": Contains, - "string_equals": EqualString, + "contained_by": ContainedBy, + "str_eq": StringEqual, + "string_equals": StringEqual, + "regex_match": RegexMatch, } -func StartsWith(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { +// StartsWith check if string starts with substring +func StartsWith(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { if !assert.IsType(t, "string", actual, fmt.Sprintf("actual is %v", actual)) { return false } @@ -44,7 +61,8 @@ func StartsWith(t assert.TestingT, expected, actual interface{}, msgAndArgs ...i return assert.True(t, strings.HasPrefix(actualString, expectedString), msgAndArgs...) } -func EndsWith(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { +// EndsWith check if string ends with substring +func EndsWith(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { if !assert.IsType(t, "string", actual, fmt.Sprintf("actual is %v", actual)) { return false } @@ -56,7 +74,7 @@ func EndsWith(t assert.TestingT, expected, actual interface{}, msgAndArgs ...int return assert.True(t, strings.HasSuffix(actualString, expectedString), msgAndArgs...) } -func EqualLength(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { +func EqualLength(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { length, err := convertInt(expected) if err != nil { return assert.Fail(t, fmt.Sprintf("expected type is not int, got %#v", expected), msgAndArgs...) @@ -65,7 +83,7 @@ func EqualLength(t assert.TestingT, expected, actual interface{}, msgAndArgs ... return assert.Len(t, actual, length, msgAndArgs...) } -func GreaterThanLength(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { +func GreaterThanLength(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { length, err := convertInt(expected) if err != nil { return assert.Fail(t, fmt.Sprintf("expected type is not int, got %#v", expected), msgAndArgs...) @@ -80,7 +98,7 @@ func GreaterThanLength(t assert.TestingT, expected, actual interface{}, msgAndAr return true } -func GreaterOrEqualsLength(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { +func GreaterOrEqualsLength(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { length, err := convertInt(expected) if err != nil { return assert.Fail(t, fmt.Sprintf("expected type is not int, got %#v", expected), msgAndArgs...) @@ -95,7 +113,7 @@ func GreaterOrEqualsLength(t assert.TestingT, expected, actual interface{}, msgA return true } -func LessThanLength(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { +func LessThanLength(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { length, err := convertInt(expected) if err != nil { return assert.Fail(t, fmt.Sprintf("expected type is not int, got %#v", expected), msgAndArgs...) @@ -110,7 +128,7 @@ func LessThanLength(t assert.TestingT, expected, actual interface{}, msgAndArgs return true } -func LessOrEqualsLength(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { +func LessOrEqualsLength(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { length, err := convertInt(expected) if err != nil { return assert.Fail(t, fmt.Sprintf("expected type is not int, got %#v", expected), msgAndArgs...) @@ -125,6 +143,27 @@ func LessOrEqualsLength(t assert.TestingT, expected, actual interface{}, msgAndA return true } +// ContainedBy assert whether actual element contains expected element +func ContainedBy(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { + return assert.Contains(t, expected, actual, msgAndArgs) +} + +func StringEqual(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { + if !assert.IsType(t, "string", actual, msgAndArgs) { + return false + } + if !assert.IsType(t, "string", expected, msgAndArgs) { + return false + } + actualString := actual.(string) + expectedString := expected.(string) + return assert.True(t, strings.EqualFold(actualString, expectedString), msgAndArgs) +} + +func RegexMatch(t assert.TestingT, actual, expected interface{}, msgAndArgs ...interface{}) bool { + return assert.Regexp(t, expected, actual, msgAndArgs) +} + func convertInt(value interface{}) (int, error) { switch v := value.(type) { case int: @@ -152,23 +191,6 @@ func convertInt(value interface{}) (int, error) { } } -// Contains assert whether actual element contains expected element -func Contains(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - return assert.Contains(t, actual, expected, msgAndArgs) -} - -func EqualString(t assert.TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { - if !assert.IsType(t, "string", actual, msgAndArgs) { - return false - } - if !assert.IsType(t, "string", expected, msgAndArgs) { - return false - } - actualString := actual.(string) - expectedString := expected.(string) - return assert.True(t, strings.EqualFold(actualString, expectedString), msgAndArgs) -} - // getLen try to get length of object. // return (false, 0) if impossible. func getLen(x interface{}) (ok bool, length int) { diff --git a/internal/builtin/assertion_test.go b/internal/builtin/assertion_test.go index 52d8d5d0..d919464e 100644 --- a/internal/builtin/assertion_test.go +++ b/internal/builtin/assertion_test.go @@ -1,6 +1,7 @@ package builtin import ( + "regexp" "testing" "github.com/stretchr/testify/assert" @@ -18,7 +19,7 @@ func TestStartsWith(t *testing.T) { } for _, data := range testData { - if !assert.True(t, StartsWith(t, data.expected, data.raw)) { + if !assert.True(t, StartsWith(t, data.raw, data.expected)) { t.Fail() } } @@ -36,7 +37,7 @@ func TestEndsWith(t *testing.T) { } for _, data := range testData { - if !assert.True(t, EndsWith(t, data.expected, data.raw)) { + if !assert.True(t, EndsWith(t, data.raw, data.expected)) { t.Fail() } } @@ -56,7 +57,7 @@ func TestEqualLength(t *testing.T) { } for _, data := range testData { - if !assert.True(t, EqualLength(t, data.expected, data.raw)) { + if !assert.True(t, EqualLength(t, data.raw, data.expected)) { t.Fail() } } @@ -76,7 +77,7 @@ func TestLessThanLength(t *testing.T) { } for _, data := range testData { - if !assert.True(t, LessThanLength(t, data.expected, data.raw)) { + if !assert.True(t, LessThanLength(t, data.raw, data.expected)) { t.Fail() } } @@ -96,7 +97,7 @@ func TestLessOrEqualsLength(t *testing.T) { } for _, data := range testData { - if !assert.True(t, LessOrEqualsLength(t, data.expected, data.raw)) { + if !assert.True(t, LessOrEqualsLength(t, data.raw, data.expected)) { t.Fail() } } @@ -113,7 +114,7 @@ func TestGreaterThanLength(t *testing.T) { } for _, data := range testData { - if !assert.True(t, GreaterThanLength(t, data.expected, data.raw)) { + if !assert.True(t, GreaterThanLength(t, data.raw, data.expected)) { t.Fail() } } @@ -133,7 +134,57 @@ func TestGreaterOrEqualsLength(t *testing.T) { } for _, data := range testData { - if !assert.True(t, GreaterOrEqualsLength(t, data.expected, data.raw)) { + if !assert.True(t, GreaterOrEqualsLength(t, data.raw, data.expected)) { + t.Fail() + } + } +} + +func TestContainedBy(t *testing.T) { + testData := []struct { + raw interface{} + expected interface{} + }{ + {"abcd", "abcdefg"}, + {"a", []string{"a", "b", "c"}}, + {"A", map[string]interface{}{"A": 111, "B": 222}}, + } + + for _, data := range testData { + if !assert.True(t, ContainedBy(t, data.raw, data.expected)) { + t.Fail() + } + } +} + +func TestStringEqual(t *testing.T) { + testData := []struct { + raw interface{} + expected interface{} + }{ + {"abcd", "abcd"}, + {"abcd", "ABCD"}, + {"ABcd", "abCD"}, + } + + for _, data := range testData { + if !assert.True(t, StringEqual(t, data.raw, data.expected)) { + t.Fail() + } + } +} + +func TestRegexMatch(t *testing.T) { + testData := []struct { + raw interface{} + expected interface{} + }{ + {"it's starting...", regexp.MustCompile("start")}, + {"it's not starting", "starting$"}, + } + + for _, data := range testData { + if !assert.True(t, RegexMatch(t, data.raw, data.expected)) { t.Fail() } } diff --git a/response.go b/response.go index 94a27d5b..8dc2ebba 100644 --- a/response.go +++ b/response.go @@ -115,7 +115,10 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s // get assert method assertMethod := validator.Assert - assertFunc := builtin.Assertions[assertMethod] + assertFunc, ok := builtin.Assertions[assertMethod] + if !ok { + return errors.New(fmt.Sprintf("unexpected assertion method: %v", assertMethod)) + } // parse expected value expectValue, err := v.parser.parseData(validator.Expect, variablesMapping) @@ -134,7 +137,7 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s } // do assertion - result := assertFunc(v.t, expectValue, checkValue) + result := assertFunc(v.t, checkValue, expectValue) if result { validResult.CheckResult = "pass" } From 5bce59c583573bd5af0a14ff0097e51fb9bcb531 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Mon, 14 Feb 2022 14:41:15 +0800 Subject: [PATCH 05/11] fix starts_with and ends_wih spelling Change-Id: I1e475e8187f6e793cd9f9029af93a7d80603b26d --- docs/BUILTIN.md | 6 +- docs/CHANGELOG.md | 2 +- docs/cmd/hrp.md | 2 +- docs/cmd/hrp_boom.md | 2 +- docs/cmd/hrp_har2case.md | 2 +- docs/cmd/hrp_run.md | 2 +- docs/cmd/hrp_startproject.md | 2 +- examples/demo.json | 2 +- examples/demo.yaml | 2 +- examples/httpbingo_test.json | 61 ++++++++++- report.html | 207 +++++++++++++++++++++++++++++++++++ response.go | 6 +- validate.go | 4 +- 13 files changed, 278 insertions(+), 22 deletions(-) create mode 100644 report.html diff --git a/docs/BUILTIN.md b/docs/BUILTIN.md index a4b9305b..064bda60 100644 --- a/docs/BUILTIN.md +++ b/docs/BUILTIN.md @@ -42,9 +42,9 @@ Currently, HttpRunner+ has the following built-in assertion functions. | `contains` | contains | [1, 2] contains 1 | 'abc' contains 'a', [1,2,3] len_lt 4 | | `contained_by` | contained by | A in B | 'a' contained_by 'abc', 1 contained_by [1,2] | | `type_match` | A and B are in the same type | type(A) == type(B) | 123 type_match 1 | -| `regex_match` | regex matches | re.match(B, A) | 'abcdef' regex 'a\w+d' | -| `starts_with` | starts with | A.startswith(B) is True | 'abc' startswith 'ab' | -| `ends_with` | ends with | A.endswith(B) is True | 'abc' endswith 'bc' | +| `regex_match` | regex matches | re.match(B, A) | 'abcdef' regex_match 'a\w+d' | +| `starts_with` | starts with | A.starts_with(B) is True | 'abc' starts_with 'ab' | +| `ends_with` | ends with | A.ends_with(B) is True | 'abc' ends_with 'bc' | ## Builtin functions diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 1cada300..4c68900e 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,7 +2,7 @@ ## v0.6.1 (2022-02-11) -- fix: assertion function and json number parse rule +- fix: assertion function errors and json number parse rule ## v0.6.0 (2022-02-08) diff --git a/docs/cmd/hrp.md b/docs/cmd/hrp.md index 688e0c52..2a01d308 100644 --- a/docs/cmd/hrp.md +++ b/docs/cmd/hrp.md @@ -33,4 +33,4 @@ Copyright 2021 debugtalk * [hrp run](hrp_run.md) - run API test * [hrp startproject](hrp_startproject.md) - create a scaffold project -###### Auto generated by spf13/cobra on 8-Feb-2022 +###### Auto generated by spf13/cobra on 14-Feb-2022 diff --git a/docs/cmd/hrp_boom.md b/docs/cmd/hrp_boom.md index e867df88..914f747f 100644 --- a/docs/cmd/hrp_boom.md +++ b/docs/cmd/hrp_boom.md @@ -39,4 +39,4 @@ hrp boom [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 8-Feb-2022 +###### Auto generated by spf13/cobra on 14-Feb-2022 diff --git a/docs/cmd/hrp_har2case.md b/docs/cmd/hrp_har2case.md index fd05af09..504d6524 100644 --- a/docs/cmd/hrp_har2case.md +++ b/docs/cmd/hrp_har2case.md @@ -23,4 +23,4 @@ hrp har2case $har_path... [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 8-Feb-2022 \ No newline at end of file +###### Auto generated by spf13/cobra on 14-Feb-2022 diff --git a/docs/cmd/hrp_run.md b/docs/cmd/hrp_run.md index 334cd4fd..7c6ca58c 100644 --- a/docs/cmd/hrp_run.md +++ b/docs/cmd/hrp_run.md @@ -33,4 +33,4 @@ hrp run $path... [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 8-Feb-2022 +###### Auto generated by spf13/cobra on 14-Feb-2022 diff --git a/docs/cmd/hrp_startproject.md b/docs/cmd/hrp_startproject.md index 6bfcd978..1894cd0b 100644 --- a/docs/cmd/hrp_startproject.md +++ b/docs/cmd/hrp_startproject.md @@ -16,4 +16,4 @@ hrp startproject $project_name [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 8-Feb-2022 +###### Auto generated by spf13/cobra on 14-Feb-2022 diff --git a/examples/demo.json b/examples/demo.json index 198bcbaa..c59570f2 100644 --- a/examples/demo.json +++ b/examples/demo.json @@ -48,7 +48,7 @@ }, { "check": "headers.\"Content-Type\"", - "assert": "startswith", + "assert": "starts_with", "expect": "application/json" }, { diff --git a/examples/demo.yaml b/examples/demo.yaml index ed6131dc..b70adc53 100644 --- a/examples/demo.yaml +++ b/examples/demo.yaml @@ -33,7 +33,7 @@ teststeps: expect: 200 msg: check response status code - check: headers."Content-Type" - assert: startswith + assert: starts_with expect: application/json - check: body.args.foo1 assert: length_equals diff --git a/examples/httpbingo_test.json b/examples/httpbingo_test.json index b3461ee4..5f1704b2 100644 --- a/examples/httpbingo_test.json +++ b/examples/httpbingo_test.json @@ -10,21 +10,70 @@ "method": "GET", "url": "/get", "params": { - "a": 1 + "a": 1, + "foo": "I'm a happy guy" } }, "validate": [ + { + "check": "body.args.a", + "assert": "eq", + "expect": "1", + "msg": "check argument a" + }, { "check": "status_code", - "assert": "greater_than", + "assert": "lt", + "expect": 201, + "msg": "check status code" + }, + { + "check": "status_code", + "assert": "gt", "expect": 199, "msg": "check status code" }, { - "check": "body.args.a", - "assert": "equal", - "expect": "1", - "msg": "check argument a" + "check": "status_code", + "assert": "ge", + "expect": 200, + "msg": "check status code" + }, + { + "check": "status_code", + "assert": "le", + "expect": 200, + "msg": "check status code" + }, + { + "check": "status_code", + "assert": "ne", + "expect": 199, + "msg": "check status code" + }, + { + "check": "body.args.foo", + "assert": "contains", + "expect": "happy", + "msg": "check status code" + }, + { + "check": "body.args.foo", + "assert": "type_match", + "expect": "string", + "msg": "check status code" + }, + { + "check": "body.args.foo", + "assert": "starts_with", + "expect": "I'm", + "msg": "check status code" + }, + { + "check": "body.args.foo", + "assert": "type_match", + "expect": "string", + "msg": "check status code" } ] } diff --git a/report.html b/report.html new file mode 100644 index 00000000..35cf0a45 --- /dev/null +++ b/report.html @@ -0,0 +1,207 @@ + + + + TestReport + + + + + +

API Test Report

+ +

Summary

+ + + + + + + + + + + + + + + + + + + + + + + + + +
START AT2022-02-14 14:39:40.220096 +0800 CST m=+16.010080077
DURATION0 seconds
PLATFORMHttpRunnerPlus v0.6.0go1.16.8darwin-amd64
STATTESTCASES (success/fail)TESTSTEPS (success/fail/error/skip)
total (details) =>0 (0/0)0 (0/0/0/0)
+ +

Details

+ + \ No newline at end of file diff --git a/response.go b/response.go index 8dc2ebba..29619160 100644 --- a/response.go +++ b/response.go @@ -117,7 +117,7 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s assertMethod := validator.Assert assertFunc, ok := builtin.Assertions[assertMethod] if !ok { - return errors.New(fmt.Sprintf("unexpected assertion method: %v", assertMethod)) + return errors.New(fmt.Sprintf("unexpected assertMethod: %v", assertMethod)) } // parse expected value @@ -151,10 +151,10 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s if !result { v.t.Fail() return errors.New(fmt.Sprintf( - "do assertion failed, assertMethod: %v, expectValue: %v, checkValue: %v", + "do assertion failed, assertMethod: %v, checkValue: %v, expectValue: %v", assertMethod, - expectValue, checkValue, + expectValue, )) } } diff --git a/validate.go b/validate.go index 51150563..fe742b64 100644 --- a/validate.go +++ b/validate.go @@ -126,7 +126,7 @@ func (s *StepRequestValidation) AssertRegexp(jmesPath string, expected interface func (s *StepRequestValidation) AssertStartsWith(jmesPath string, expected interface{}, msg string) *StepRequestValidation { v := Validator{ Check: jmesPath, - Assert: "startswith", + Assert: "starts_with", Expect: expected, Message: msg, } @@ -137,7 +137,7 @@ func (s *StepRequestValidation) AssertStartsWith(jmesPath string, expected inter func (s *StepRequestValidation) AssertEndsWith(jmesPath string, expected interface{}, msg string) *StepRequestValidation { v := Validator{ Check: jmesPath, - Assert: "endswith", + Assert: "ends_with", Expect: expected, Message: msg, } From ef5f071dbce64585a3aceed83eb1fb3b56566e49 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Mon, 14 Feb 2022 16:02:28 +0800 Subject: [PATCH 06/11] fix: converInt function bug Change-Id: Ifb364a943351f3762f5784fb8d84d9eb385a383f --- internal/builtin/assertion.go | 4 + report.html | 207 ---------------------------------- 2 files changed, 4 insertions(+), 207 deletions(-) delete mode 100644 report.html diff --git a/internal/builtin/assertion.go b/internal/builtin/assertion.go index d7de8482..6473666e 100644 --- a/internal/builtin/assertion.go +++ b/internal/builtin/assertion.go @@ -186,6 +186,10 @@ func convertInt(value interface{}) (int, error) { return int(v), nil case uint64: return int(v), nil + case float32: + return int(v), nil + case float64: + return int(v), nil default: return 0, fmt.Errorf("unsupported int convertion for %v(%T)", v, v) } diff --git a/report.html b/report.html deleted file mode 100644 index 35cf0a45..00000000 --- a/report.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - TestReport - - - - - -

API Test Report

- -

Summary

- - - - - - - - - - - - - - - - - - - - - - - - - -
START AT2022-02-14 14:39:40.220096 +0800 CST m=+16.010080077
DURATION0 seconds
PLATFORMHttpRunnerPlus v0.6.0go1.16.8darwin-amd64
STATTESTCASES (success/fail)TESTSTEPS (success/fail/error/skip)
total (details) =>0 (0/0)0 (0/0/0/0)
- -

Details

- - \ No newline at end of file From b1fdd4be71c78e2eaee2aeaf9b012d386043a08d Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Mon, 14 Feb 2022 16:06:34 +0800 Subject: [PATCH 07/11] fix: Connection and Content-Type not found in postman-echo headers Change-Id: Ieae673e12c7baabe231d7f3509bba18624d80431 --- examples/extract_test.go | 3 --- examples/request_test.go | 2 -- examples/validate_test.go | 14 +++++--------- examples/variables_test.go | 6 ------ step_test.go | 2 -- 5 files changed, 5 insertions(+), 22 deletions(-) diff --git a/examples/extract_test.go b/examples/extract_test.go index ec72277d..ac1d27b2 100644 --- a/examples/extract_test.go +++ b/examples/extract_test.go @@ -58,12 +58,9 @@ func TestCaseExtractStepAssociation(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Extract(). WithJmesPath("status_code", "statusCode"). - WithJmesPath("headers.\"Content-Type\"", "contentType"). WithJmesPath("body.args.foo1", "varFoo1"). Validate(). AssertEqual("$statusCode", 200, "check status code"). - AssertEqual("headers.Connection", "keep-alive", "check header Connection"). - AssertEqual("$contentType", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("$varFoo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), diff --git a/examples/request_test.go b/examples/request_test.go index 6312df07..6394cee6 100644 --- a/examples/request_test.go +++ b/examples/request_test.go @@ -20,8 +20,6 @@ func TestCaseBasicRequest(t *testing.T) { }). Validate(). AssertEqual("status_code", 200, "check status code"). - AssertEqual("headers.Connection", "keep-alive", "check header Connection"). - AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"), hrp.NewStep("post raw text"). diff --git a/examples/validate_test.go b/examples/validate_test.go index 24d60e25..941ea5c0 100644 --- a/examples/validate_test.go +++ b/examples/validate_test.go @@ -24,10 +24,8 @@ func TestCaseValidateStep(t *testing.T) { Extract(). WithJmesPath("body.args.foo1", "varFoo1"). Validate(). - AssertEqual("status_code", "$expectedStatusCode", "check status code"). // assert status code - AssertEqual("headers.Connection", "keep-alive", "check header Connection"). // assert response header - AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). // assert response header, with double quotes - AssertEqual("body.args.foo1", "bar1", "check args foo1"). // assert response json body with jmespath + AssertEqual("status_code", "$expectedStatusCode", "check status code"). // assert status code + AssertEqual("body.args.foo1", "bar1", "check args foo1"). // assert response json body with jmespath AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), hrp.NewStep("get with params"). @@ -40,12 +38,10 @@ func TestCaseValidateStep(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Extract(). WithJmesPath("status_code", "statusCode"). - WithJmesPath("headers.\"Content-Type\"", "contentType"). Validate(). - AssertEqual("$statusCode", 200, "check status code"). // assert with extracted variable from current step - AssertEqual("$contentType", "application/json; charset=utf-8", "check header Content-Type"). // assert with extracted variable from current step - AssertEqual("$varFoo1", "bar1", "check args foo1"). // assert with extracted variable from previous step - AssertEqual("body.args.foo2", "bar2", "check args foo2"), // assert response json body with jmespath + AssertEqual("$statusCode", 200, "check status code"). // assert with extracted variable from current step + AssertEqual("$varFoo1", "bar1", "check args foo1"). // assert with extracted variable from previous step + AssertEqual("body.args.foo2", "bar2", "check args foo2"), // assert response json body with jmespath }, } diff --git a/examples/variables_test.go b/examples/variables_test.go index 9fb4c0fb..d9875237 100644 --- a/examples/variables_test.go +++ b/examples/variables_test.go @@ -22,8 +22,6 @@ func TestCaseConfigVariables(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Validate(). AssertEqual("status_code", "$expectedStatusCode", "check status code"). - AssertEqual("headers.Connection", "keep-alive", "check header Connection"). - AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), @@ -53,8 +51,6 @@ func TestCaseStepVariables(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Validate(). AssertEqual("status_code", "$expectedStatusCode", "check status code"). - AssertEqual("headers.Connection", "keep-alive", "check header Connection"). - AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), @@ -88,8 +84,6 @@ func TestCaseOverrideConfigVariables(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Validate(). AssertEqual("status_code", "$expectedStatusCode", "check status code"). - AssertEqual("headers.Connection", "keep-alive", "check header Connection"). - AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), diff --git a/step_test.go b/step_test.go index 5eb6427f..578f50ef 100644 --- a/step_test.go +++ b/step_test.go @@ -12,8 +12,6 @@ var ( WithCookies(map[string]string{"user": "debugtalk"}). Validate(). AssertEqual("status_code", 200, "check status code"). - AssertEqual("headers.Connection", "keep-alive", "check header Connection"). - AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check param foo1"). AssertEqual("body.args.foo2", "bar2", "check param foo2") stepPOSTData = NewStep("post form data"). From 6fbd8f7d9bd5012fe6abe397d0657f7fb51501f2 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Mon, 14 Feb 2022 16:13:22 +0800 Subject: [PATCH 08/11] fix code format Change-Id: I583aa6344fff967285b024fddef9f45ac8ee2baf --- docs/BUILTIN.md | 14 +++++--------- examples/httpbingo_test.json | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/docs/BUILTIN.md b/docs/BUILTIN.md index 064bda60..47cb6195 100644 --- a/docs/BUILTIN.md +++ b/docs/BUILTIN.md @@ -6,16 +6,12 @@ HttpRunner+ validation should follow the following format. `check`, `assert` and ```json { - "check": "status_code", - // target field, usually used with jmespath - "assert": "equals", - // assertion method, you can use builtin method or custom defined function - "expect": 200, - // expected value - "msg": "check response status code" - // optional, print this message if assertion failed + "check": "status_code", // target field, usually used with jmespath + "assert": "equals", // assertion method, you can use builtin method or custom defined function + "expect": 200, // expected value + "msg": "check response status code" // optional, print this message if assertion failed } -``` +```g The `assert` method name will be mapped to a built-in function with the following function signature. diff --git a/examples/httpbingo_test.json b/examples/httpbingo_test.json index 5f1704b2..f61b007e 100644 --- a/examples/httpbingo_test.json +++ b/examples/httpbingo_test.json @@ -78,4 +78,4 @@ ] } ] -} \ No newline at end of file +} From 3f5c6f7f5dce8f3b270fa41901aa2d8101088887 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Mon, 14 Feb 2022 16:17:28 +0800 Subject: [PATCH 09/11] fix code format Change-Id: I85d477f85844eee2d98f6231c16b57803a41aba7 --- docs/BUILTIN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/BUILTIN.md b/docs/BUILTIN.md index 47cb6195..4e818624 100644 --- a/docs/BUILTIN.md +++ b/docs/BUILTIN.md @@ -11,7 +11,7 @@ HttpRunner+ validation should follow the following format. `check`, `assert` and "expect": 200, // expected value "msg": "check response status code" // optional, print this message if assertion failed } -```g +``` The `assert` method name will be mapped to a built-in function with the following function signature. From e6467dfc280fe70d929d4e882e4631c0f0418ec4 Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Tue, 15 Feb 2022 17:05:39 +0800 Subject: [PATCH 10/11] fix startswith endswith and unittest Change-Id: I3e1c6fd82812d13b4e23ecd6b23c4d57170852e1 --- docs/BUILTIN.md | 4 +- docs/cmd/hrp.md | 2 +- docs/cmd/hrp_boom.md | 2 +- docs/cmd/hrp_har2case.md | 2 +- docs/cmd/hrp_run.md | 2 +- docs/cmd/hrp_startproject.md | 2 +- examples/demo.json | 2 +- examples/demo.yaml | 2 +- examples/extract_test.go | 2 + examples/httpbingo_test.json | 81 ----------------------------------- examples/request_test.go | 1 + examples/validate_test.go | 5 ++- examples/variables_test.go | 3 ++ internal/builtin/assertion.go | 4 +- step_test.go | 1 + validate.go | 4 +- 16 files changed, 23 insertions(+), 96 deletions(-) delete mode 100644 examples/httpbingo_test.json diff --git a/docs/BUILTIN.md b/docs/BUILTIN.md index 4e818624..899e822c 100644 --- a/docs/BUILTIN.md +++ b/docs/BUILTIN.md @@ -39,8 +39,8 @@ Currently, HttpRunner+ has the following built-in assertion functions. | `contained_by` | contained by | A in B | 'a' contained_by 'abc', 1 contained_by [1,2] | | `type_match` | A and B are in the same type | type(A) == type(B) | 123 type_match 1 | | `regex_match` | regex matches | re.match(B, A) | 'abcdef' regex_match 'a\w+d' | -| `starts_with` | starts with | A.starts_with(B) is True | 'abc' starts_with 'ab' | -| `ends_with` | ends with | A.ends_with(B) is True | 'abc' ends_with 'bc' | +| `startswith` | starts with | A.startswith(B) is True | 'abc' startswith 'ab' | +| `endswith` | ends with | A.endswith(B) is True | 'abc' endswith 'bc' | ## Builtin functions diff --git a/docs/cmd/hrp.md b/docs/cmd/hrp.md index 2a01d308..9d12a34e 100644 --- a/docs/cmd/hrp.md +++ b/docs/cmd/hrp.md @@ -33,4 +33,4 @@ Copyright 2021 debugtalk * [hrp run](hrp_run.md) - run API test * [hrp startproject](hrp_startproject.md) - create a scaffold project -###### Auto generated by spf13/cobra on 14-Feb-2022 +###### Auto generated by spf13/cobra on 15-Feb-2022 diff --git a/docs/cmd/hrp_boom.md b/docs/cmd/hrp_boom.md index 914f747f..a0dcf982 100644 --- a/docs/cmd/hrp_boom.md +++ b/docs/cmd/hrp_boom.md @@ -39,4 +39,4 @@ hrp boom [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 14-Feb-2022 +###### Auto generated by spf13/cobra on 15-Feb-2022 diff --git a/docs/cmd/hrp_har2case.md b/docs/cmd/hrp_har2case.md index 504d6524..a24d244b 100644 --- a/docs/cmd/hrp_har2case.md +++ b/docs/cmd/hrp_har2case.md @@ -23,4 +23,4 @@ hrp har2case $har_path... [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 14-Feb-2022 +###### Auto generated by spf13/cobra on 15-Feb-2022 diff --git a/docs/cmd/hrp_run.md b/docs/cmd/hrp_run.md index 7c6ca58c..2c781641 100644 --- a/docs/cmd/hrp_run.md +++ b/docs/cmd/hrp_run.md @@ -33,4 +33,4 @@ hrp run $path... [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 14-Feb-2022 +###### Auto generated by spf13/cobra on 15-Feb-2022 diff --git a/docs/cmd/hrp_startproject.md b/docs/cmd/hrp_startproject.md index 1894cd0b..7921fc50 100644 --- a/docs/cmd/hrp_startproject.md +++ b/docs/cmd/hrp_startproject.md @@ -16,4 +16,4 @@ hrp startproject $project_name [flags] * [hrp](hrp.md) - One-stop solution for HTTP(S) testing. -###### Auto generated by spf13/cobra on 14-Feb-2022 +###### Auto generated by spf13/cobra on 15-Feb-2022 diff --git a/examples/demo.json b/examples/demo.json index c59570f2..198bcbaa 100644 --- a/examples/demo.json +++ b/examples/demo.json @@ -48,7 +48,7 @@ }, { "check": "headers.\"Content-Type\"", - "assert": "starts_with", + "assert": "startswith", "expect": "application/json" }, { diff --git a/examples/demo.yaml b/examples/demo.yaml index b70adc53..ed6131dc 100644 --- a/examples/demo.yaml +++ b/examples/demo.yaml @@ -33,7 +33,7 @@ teststeps: expect: 200 msg: check response status code - check: headers."Content-Type" - assert: starts_with + assert: startswith expect: application/json - check: body.args.foo1 assert: length_equals diff --git a/examples/extract_test.go b/examples/extract_test.go index ac1d27b2..0d1184bd 100644 --- a/examples/extract_test.go +++ b/examples/extract_test.go @@ -58,9 +58,11 @@ func TestCaseExtractStepAssociation(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Extract(). WithJmesPath("status_code", "statusCode"). + WithJmesPath("headers.\"Content-Type\"", "contentType"). WithJmesPath("body.args.foo1", "varFoo1"). Validate(). AssertEqual("$statusCode", 200, "check status code"). + AssertEqual("$contentType", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("$varFoo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), diff --git a/examples/httpbingo_test.json b/examples/httpbingo_test.json deleted file mode 100644 index f61b007e..00000000 --- a/examples/httpbingo_test.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "config": { - "name": "request methods testcase: validate with parameters", - "base_url": "https://httpbingo.bytedance.net" - }, - "teststeps": [ - { - "name": "get with params", - "request": { - "method": "GET", - "url": "/get", - "params": { - "a": 1, - "foo": "I'm a happy guy" - } - }, - "validate": [ - { - "check": "body.args.a", - "assert": "eq", - "expect": "1", - "msg": "check argument a" - }, - { - "check": "status_code", - "assert": "lt", - "expect": 201, - "msg": "check status code" - }, - { - "check": "status_code", - "assert": "gt", - "expect": 199, - "msg": "check status code" - }, - { - "check": "status_code", - "assert": "ge", - "expect": 200, - "msg": "check status code" - }, - { - "check": "status_code", - "assert": "le", - "expect": 200, - "msg": "check status code" - }, - { - "check": "status_code", - "assert": "ne", - "expect": 199, - "msg": "check status code" - }, - { - "check": "body.args.foo", - "assert": "contains", - "expect": "happy", - "msg": "check status code" - }, - { - "check": "body.args.foo", - "assert": "type_match", - "expect": "string", - "msg": "check status code" - }, - { - "check": "body.args.foo", - "assert": "starts_with", - "expect": "I'm", - "msg": "check status code" - }, - { - "check": "body.args.foo", - "assert": "type_match", - "expect": "string", - "msg": "check status code" - } - ] - } - ] -} diff --git a/examples/request_test.go b/examples/request_test.go index 6394cee6..2a8a2383 100644 --- a/examples/request_test.go +++ b/examples/request_test.go @@ -20,6 +20,7 @@ func TestCaseBasicRequest(t *testing.T) { }). Validate(). AssertEqual("status_code", 200, "check status code"). + AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"), hrp.NewStep("post raw text"). diff --git a/examples/validate_test.go b/examples/validate_test.go index 941ea5c0..4f27075f 100644 --- a/examples/validate_test.go +++ b/examples/validate_test.go @@ -24,8 +24,9 @@ func TestCaseValidateStep(t *testing.T) { Extract(). WithJmesPath("body.args.foo1", "varFoo1"). Validate(). - AssertEqual("status_code", "$expectedStatusCode", "check status code"). // assert status code - AssertEqual("body.args.foo1", "bar1", "check args foo1"). // assert response json body with jmespath + AssertEqual("status_code", "$expectedStatusCode", "check status code"). // assert status code + AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). // assert response header, with double quotes + AssertEqual("body.args.foo1", "bar1", "check args foo1"). // assert response json body with jmespath AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), hrp.NewStep("get with params"). diff --git a/examples/variables_test.go b/examples/variables_test.go index d9875237..d1f856fc 100644 --- a/examples/variables_test.go +++ b/examples/variables_test.go @@ -22,6 +22,7 @@ func TestCaseConfigVariables(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Validate(). AssertEqual("status_code", "$expectedStatusCode", "check status code"). + AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), @@ -51,6 +52,7 @@ func TestCaseStepVariables(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Validate(). AssertEqual("status_code", "$expectedStatusCode", "check status code"). + AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), @@ -84,6 +86,7 @@ func TestCaseOverrideConfigVariables(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Validate(). AssertEqual("status_code", "$expectedStatusCode", "check status code"). + AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check args foo1"). AssertEqual("body.args.foo2", "bar2", "check args foo2"). AssertEqual("body.headers.\"user-agent\"", "HttpRunnerPlus", "check header user agent"), diff --git a/internal/builtin/assertion.go b/internal/builtin/assertion.go index 6473666e..01eb3157 100644 --- a/internal/builtin/assertion.go +++ b/internal/builtin/assertion.go @@ -25,8 +25,8 @@ var Assertions = map[string]func(t assert.TestingT, actual interface{}, expected "contains": assert.Contains, "type_match": assert.IsType, // custom assertions - "starts_with": StartsWith, - "ends_with": EndsWith, + "startswith": StartsWith, + "endswith": EndsWith, "len_eq": EqualLength, "length_equals": EqualLength, "length_equal": EqualLength, diff --git a/step_test.go b/step_test.go index 578f50ef..b81b48d3 100644 --- a/step_test.go +++ b/step_test.go @@ -12,6 +12,7 @@ var ( WithCookies(map[string]string{"user": "debugtalk"}). Validate(). AssertEqual("status_code", 200, "check status code"). + AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type"). AssertEqual("body.args.foo1", "bar1", "check param foo1"). AssertEqual("body.args.foo2", "bar2", "check param foo2") stepPOSTData = NewStep("post form data"). diff --git a/validate.go b/validate.go index fe742b64..51150563 100644 --- a/validate.go +++ b/validate.go @@ -126,7 +126,7 @@ func (s *StepRequestValidation) AssertRegexp(jmesPath string, expected interface func (s *StepRequestValidation) AssertStartsWith(jmesPath string, expected interface{}, msg string) *StepRequestValidation { v := Validator{ Check: jmesPath, - Assert: "starts_with", + Assert: "startswith", Expect: expected, Message: msg, } @@ -137,7 +137,7 @@ func (s *StepRequestValidation) AssertStartsWith(jmesPath string, expected inter func (s *StepRequestValidation) AssertEndsWith(jmesPath string, expected interface{}, msg string) *StepRequestValidation { v := Validator{ Check: jmesPath, - Assert: "ends_with", + Assert: "endswith", Expect: expected, Message: msg, } From 158bc160bbfeb0e1ec5c1fe1d96fd5581e5bdaba Mon Sep 17 00:00:00 2001 From: buyuxiang <347586493@qq.com> Date: Tue, 15 Feb 2022 17:10:38 +0800 Subject: [PATCH 11/11] restore headers.Content-Type validate Change-Id: I6fdf2291bdf953f19ee6e9474020a2ab72186acf --- examples/validate_test.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/validate_test.go b/examples/validate_test.go index 4f27075f..95ff040b 100644 --- a/examples/validate_test.go +++ b/examples/validate_test.go @@ -39,10 +39,12 @@ func TestCaseValidateStep(t *testing.T) { WithHeaders(map[string]string{"User-Agent": "$agent"}). Extract(). WithJmesPath("status_code", "statusCode"). + WithJmesPath("headers.\"Content-Type\"", "contentType"). Validate(). - AssertEqual("$statusCode", 200, "check status code"). // assert with extracted variable from current step - AssertEqual("$varFoo1", "bar1", "check args foo1"). // assert with extracted variable from previous step - AssertEqual("body.args.foo2", "bar2", "check args foo2"), // assert response json body with jmespath + AssertEqual("$statusCode", 200, "check status code"). // assert with extracted variable from current step + AssertEqual("$contentType", "application/json; charset=utf-8", "check header Content-Type"). // assert with extracted variable from current step + AssertEqual("$varFoo1", "bar1", "check args foo1"). // assert with extracted variable from previous step + AssertEqual("body.args.foo2", "bar2", "check args foo2"), // assert response json body with jmespath }, }