mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
Merge pull request #97 from bbx-winner/main
fix #97: incorrect data type when extracting data using jmespath
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# Release History
|
||||
|
||||
## v0.6.2 (2022-02-18)
|
||||
|
||||
## v0.6.2 (2022-02-20)
|
||||
- fix: omit pseudo header names for HTTP/1, e.g. :authority
|
||||
- fix: generate `headers.\"Content-Type\"` in har2case
|
||||
- change: json unmarshal to json.Number when parsing data
|
||||
- fix: incorrect data type when extracting data using jmespath
|
||||
|
||||
## v0.6.1 (2022-02-17)
|
||||
|
||||
|
||||
@@ -119,9 +119,13 @@
|
||||
},
|
||||
"body": {
|
||||
"foo1": "$varFoo1",
|
||||
"foo2": "${max($a, $b)}"
|
||||
"foo2": "${max($a, $b)}",
|
||||
"time": "${get_timestamp()}"
|
||||
}
|
||||
},
|
||||
"extract": {
|
||||
"varTime": "body.form.time"
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "status_code",
|
||||
@@ -142,6 +146,24 @@
|
||||
"msg": "check args foo2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "get with timestamp",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "/get",
|
||||
"params": {
|
||||
"time": "$varTime"
|
||||
}
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "body.args.time",
|
||||
"assert": "length_equals",
|
||||
"expect": 13,
|
||||
"msg": "check extracted var timestamp"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,9 @@ teststeps:
|
||||
body:
|
||||
foo1: $varFoo1
|
||||
foo2: ${max($a, $b)}
|
||||
time: ${get_timestamp()}
|
||||
extract:
|
||||
varTime: body.form.time
|
||||
validate:
|
||||
- check: status_code
|
||||
assert: equals
|
||||
@@ -93,3 +96,14 @@ teststeps:
|
||||
assert: equals
|
||||
expect: "12.3"
|
||||
msg: check args foo2
|
||||
- name: get with timestamp
|
||||
request:
|
||||
method: GET
|
||||
url: /get
|
||||
params:
|
||||
time: $varTime
|
||||
validate:
|
||||
- check: body.args.time
|
||||
assert: length_equals
|
||||
expect: 13
|
||||
msg: check extracted var timestamp
|
||||
|
||||
@@ -48,11 +48,18 @@ var demoTestCase = &hrp.TestCase{
|
||||
WithBody(map[string]interface{}{
|
||||
"foo1": "$varFoo1", // reference former extracted variable
|
||||
"foo2": "${max($a, $b)}", // 12.3; step level variables are independent, variable b is 3.45 here
|
||||
"time": "${get_timestamp()}",
|
||||
}).
|
||||
Extract().
|
||||
WithJmesPath("body.form.time", "varTime").
|
||||
Validate().
|
||||
AssertEqual("status_code", 200, "check status code").
|
||||
AssertLengthEqual("body.form.foo1", 5, "check args foo1").
|
||||
AssertEqual("body.form.foo2", "12.3", "check args foo2"), // form data will be converted to string
|
||||
hrp.NewStep("get with timestamp").
|
||||
GET("/get").WithParams(map[string]interface{}{"time": "$varTime"}).
|
||||
Validate().
|
||||
AssertLengthEqual("body.args.time", 13, "check extracted var timestamp"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
13
parser.go
13
parser.go
@@ -69,8 +69,7 @@ func (p *parser) parseData(raw interface{}, variablesMapping map[string]interfac
|
||||
case reflect.String:
|
||||
// json.Number
|
||||
if rawValue, ok := raw.(json.Number); ok {
|
||||
// use the same rule as json.Unmarshal (float64, for JSON numbers)
|
||||
return rawValue.Float64()
|
||||
return parseJSONNumber(rawValue)
|
||||
}
|
||||
// other string
|
||||
value := rawValue.String()
|
||||
@@ -109,6 +108,16 @@ 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
|
||||
|
||||
12
response.go
12
response.go
@@ -1,6 +1,7 @@
|
||||
package hrp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -53,7 +54,9 @@ func newResponseObject(t *testing.T, parser *parser, resp *http.Response) (*resp
|
||||
// convert respObjMeta to interface{}
|
||||
respObjMetaBytes, _ := json.Marshal(respObjMeta)
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(respObjMetaBytes, &data); err != nil {
|
||||
decoder := json.NewDecoder(bytes.NewReader(respObjMetaBytes))
|
||||
decoder.UseNumber()
|
||||
if err := decoder.Decode(&data); err != nil {
|
||||
log.Error().
|
||||
Str("respObjMeta", string(respObjMetaBytes)).
|
||||
Err(err).
|
||||
@@ -167,5 +170,12 @@ func (v *responseObject) searchJmespath(expr string) interface{} {
|
||||
log.Error().Str("expr", expr).Err(err).Msg("search jmespath failed")
|
||||
return expr // jmespath not found, return the expression
|
||||
}
|
||||
if number, ok := checkValue.(json.Number); ok {
|
||||
checkNumber, err := parseJSONNumber(number)
|
||||
if err != nil {
|
||||
log.Error().Interface("json number", number).Err(err).Msg("convert json number failed")
|
||||
}
|
||||
return checkNumber
|
||||
}
|
||||
return checkValue
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user