mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-10 02:09:51 +08:00
Merge pull request #118 from bbx-winner/main
compat: support testcase generated by HttpRunner
This commit is contained in:
79
convert.go
79
convert.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -29,6 +30,10 @@ func loadFromJSON(path string) (*TCase, error) {
|
|||||||
decoder := json.NewDecoder(bytes.NewReader(file))
|
decoder := json.NewDecoder(bytes.NewReader(file))
|
||||||
decoder.UseNumber()
|
decoder.UseNumber()
|
||||||
err = decoder.Decode(tc)
|
err = decoder.Decode(tc)
|
||||||
|
if err != nil {
|
||||||
|
return tc, err
|
||||||
|
}
|
||||||
|
err = convertCompatTestCase(tc)
|
||||||
return tc, err
|
return tc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,9 +53,83 @@ func loadFromYAML(path string) (*TCase, error) {
|
|||||||
|
|
||||||
tc := &TCase{}
|
tc := &TCase{}
|
||||||
err = yaml.Unmarshal(file, tc)
|
err = yaml.Unmarshal(file, tc)
|
||||||
|
if err != nil {
|
||||||
|
return tc, nil
|
||||||
|
}
|
||||||
|
err = convertCompatTestCase(tc)
|
||||||
return tc, err
|
return tc, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convertCompatTestCase(tc *TCase) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if p := recover(); p != nil {
|
||||||
|
err = fmt.Errorf("convert compat testcase error: %v", p)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for _, step := range tc.TestSteps {
|
||||||
|
// 1. deal with request body compatible with HttpRunner
|
||||||
|
if step.Request != nil && step.Request.Body == nil {
|
||||||
|
if step.Request.Json != nil {
|
||||||
|
step.Request.Headers["Content-Type"] = "application/json; charset=utf-8"
|
||||||
|
step.Request.Body = step.Request.Json
|
||||||
|
} else if step.Request.Data != nil {
|
||||||
|
step.Request.Body = step.Request.Data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. deal with validators compatible with HttpRunner
|
||||||
|
for i, iValidator := range step.Validators {
|
||||||
|
validatorMap := iValidator.(map[string]interface{})
|
||||||
|
validator := Validator{}
|
||||||
|
_, checkExisted := validatorMap["check"]
|
||||||
|
_, assertExisted := validatorMap["assert"]
|
||||||
|
_, expectExisted := validatorMap["expect"]
|
||||||
|
// check priority: HRP > HttpRunner
|
||||||
|
if checkExisted && assertExisted && expectExisted {
|
||||||
|
// HRP validator format
|
||||||
|
validator.Check = validatorMap["check"].(string)
|
||||||
|
validator.Assert = validatorMap["assert"].(string)
|
||||||
|
validator.Expect = validatorMap["expect"]
|
||||||
|
if msg, existed := validatorMap["msg"]; existed {
|
||||||
|
validator.Message = msg.(string)
|
||||||
|
}
|
||||||
|
validator.Check = convertCheckExpr(validator.Check)
|
||||||
|
step.Validators[i] = validator
|
||||||
|
} else if len(validatorMap) == 1 {
|
||||||
|
// HttpRunner validator format
|
||||||
|
for assertMethod, iValidatorContent := range validatorMap {
|
||||||
|
checkAndExpect := iValidatorContent.([]interface{})
|
||||||
|
if len(checkAndExpect) != 2 {
|
||||||
|
return fmt.Errorf("unexpected validator format: %v", validatorMap)
|
||||||
|
}
|
||||||
|
validator.Check = checkAndExpect[0].(string)
|
||||||
|
validator.Assert = assertMethod
|
||||||
|
validator.Expect = checkAndExpect[1]
|
||||||
|
}
|
||||||
|
validator.Check = convertCheckExpr(validator.Check)
|
||||||
|
step.Validators[i] = validator
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("unexpected validator format: %v", validatorMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertCheckExpr deals with check expression including hyphen
|
||||||
|
func convertCheckExpr(checkExpr string) string {
|
||||||
|
if strings.Contains(checkExpr, textExtractorSubRegexp) {
|
||||||
|
return checkExpr
|
||||||
|
}
|
||||||
|
checkItems := strings.Split(checkExpr, ".")
|
||||||
|
for i, checkItem := range checkItems {
|
||||||
|
if strings.Contains(checkItem, "-") && !strings.Contains(checkItem, "\"") {
|
||||||
|
checkItems[i] = fmt.Sprintf("\"%s\"", checkItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(checkItems, ".")
|
||||||
|
}
|
||||||
|
|
||||||
func (tc *TCase) ToTestCase() (*TestCase, error) {
|
func (tc *TCase) ToTestCase() (*TestCase, error) {
|
||||||
testCase := &TestCase{
|
testCase := &TestCase{
|
||||||
Config: tc.Config,
|
Config: tc.Config,
|
||||||
|
|||||||
@@ -34,3 +34,30 @@ func TestLoadCase(t *testing.T) {
|
|||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_convertCheckExpr(t *testing.T) {
|
||||||
|
exprs := []struct {
|
||||||
|
before string
|
||||||
|
after string
|
||||||
|
}{
|
||||||
|
// normal check expression
|
||||||
|
{"a.b.c", "a.b.c"},
|
||||||
|
{"headers.\"Content-Type\"", "headers.\"Content-Type\""},
|
||||||
|
// check expression using regex
|
||||||
|
{"covering (.*) testing,", "covering (.*) testing,"},
|
||||||
|
{" (.*) a-b-c", " (.*) a-b-c"},
|
||||||
|
// abnormal check expression
|
||||||
|
{"-", "\"-\""},
|
||||||
|
{"b-c", "\"b-c\""},
|
||||||
|
{"a.b-c.d", "a.\"b-c\".d"},
|
||||||
|
{"a-b.c-d", "\"a-b\".\"c-d\""},
|
||||||
|
{"\"a-b\".c-d", "\"a-b\".\"c-d\""},
|
||||||
|
{"headers.Content-Type", "headers.\"Content-Type\""},
|
||||||
|
{"body.I-am-a-Key.name", "body.\"I-am-a-Key\".name"},
|
||||||
|
}
|
||||||
|
for _, expr := range exprs {
|
||||||
|
if !assert.Equal(t, convertCheckExpr(expr.before), expr.after) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
## v0.6.3 (2022-02-22)
|
## v0.6.3 (2022-03-03)
|
||||||
|
|
||||||
- feat: support customized setup/teardown hooks (variable assignment not supported)
|
- feat: support customized setup/teardown hooks (variable assignment not supported)
|
||||||
|
- compat: support testcase generated by HttpRunner
|
||||||
|
|
||||||
## v0.6.2 (2022-02-22)
|
## v0.6.2 (2022-02-22)
|
||||||
|
|
||||||
|
|||||||
25
examples/compat_test.go
Normal file
25
examples/compat_test.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package examples
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/httprunner/hrp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// generated by examples/har/demo.har using HttpRunner v3.1.6
|
||||||
|
const demoHttpRunnerJSONPath = "demo_httprunner.json"
|
||||||
|
const demoHttpRunnerYAMLPath = "demo_httprunner.yaml"
|
||||||
|
|
||||||
|
func TestCompatTestCase(t *testing.T) {
|
||||||
|
testcaseFromJSON := &hrp.TestCasePath{Path: demoHttpRunnerJSONPath}
|
||||||
|
err := hrp.NewRunner(t).Run(testcaseFromJSON)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("run testcase error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
testcaseFromYAML := &hrp.TestCasePath{Path: demoHttpRunnerYAMLPath}
|
||||||
|
err = hrp.NewRunner(t).Run(testcaseFromYAML)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("run testcase error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
135
examples/demo_httprunner.json
Normal file
135
examples/demo_httprunner.json
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"name": "testcase description",
|
||||||
|
"variables": {},
|
||||||
|
"verify": false
|
||||||
|
},
|
||||||
|
"teststeps": [
|
||||||
|
{
|
||||||
|
"name": "/get",
|
||||||
|
"request": {
|
||||||
|
"url": "https://postman-echo.com/get",
|
||||||
|
"params": {
|
||||||
|
"foo1": "HDnY8",
|
||||||
|
"foo2": "34.5"
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"headers": {
|
||||||
|
"Host": "postman-echo.com",
|
||||||
|
"User-Agent": "HttpRunnerPlus",
|
||||||
|
"Accept-Encoding": "gzip"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"validate": [
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"status_code",
|
||||||
|
200
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"headers.Content-Type",
|
||||||
|
"application/json; charset=utf-8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"body.url",
|
||||||
|
"https://postman-echo.com/get?foo1=HDnY8&foo2=34.5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "/post",
|
||||||
|
"request": {
|
||||||
|
"url": "https://postman-echo.com/post",
|
||||||
|
"method": "POST",
|
||||||
|
"cookies": {
|
||||||
|
"sails.sid": "s%3Az_LpglkKxTvJ_eHVUH6V67drKp0AGWW-.PidabaXOnatLRP47hVyqqepl6BdrpEQzRlJQXtbIiwk"
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"Host": "postman-echo.com",
|
||||||
|
"User-Agent": "Go-http-client/1.1",
|
||||||
|
"Content-Length": "28",
|
||||||
|
"Content-Type": "application/json; charset=UTF-8",
|
||||||
|
"Cookie": "sails.sid=s%3Az_LpglkKxTvJ_eHVUH6V67drKp0AGWW-.PidabaXOnatLRP47hVyqqepl6BdrpEQzRlJQXtbIiwk",
|
||||||
|
"Accept-Encoding": "gzip"
|
||||||
|
},
|
||||||
|
"json": {
|
||||||
|
"foo1": "HDnY8",
|
||||||
|
"foo2": 12.3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"validate": [
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"status_code",
|
||||||
|
200
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"headers.Content-Type",
|
||||||
|
"application/json; charset=utf-8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"body.url",
|
||||||
|
"https://postman-echo.com/post"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "/post",
|
||||||
|
"request": {
|
||||||
|
"url": "https://postman-echo.com/post",
|
||||||
|
"method": "POST",
|
||||||
|
"cookies": {
|
||||||
|
"sails.sid": "s%3AS5e7w0zQ0xAsCwh9L8T6R7QLYCO7_gtD.r8%2B2w9IWqEIfuVkrZjnxzm2xADIk34zKAWXRPapr%2FAw"
|
||||||
|
},
|
||||||
|
"headers": {
|
||||||
|
"Host": "postman-echo.com",
|
||||||
|
"User-Agent": "Go-http-client/1.1",
|
||||||
|
"Content-Length": "20",
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||||
|
"Cookie": "sails.sid=s%3AS5e7w0zQ0xAsCwh9L8T6R7QLYCO7_gtD.r8%2B2w9IWqEIfuVkrZjnxzm2xADIk34zKAWXRPapr%2FAw",
|
||||||
|
"Accept-Encoding": "gzip"
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"foo1": "HDnY8",
|
||||||
|
"foo2": "12.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"validate": [
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"status_code",
|
||||||
|
200
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"headers.Content-Type",
|
||||||
|
"application/json; charset=utf-8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"body.data",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"eq": [
|
||||||
|
"body.url",
|
||||||
|
"https://postman-echo.com/post"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
81
examples/demo_httprunner.yaml
Normal file
81
examples/demo_httprunner.yaml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
config:
|
||||||
|
name: testcase description
|
||||||
|
variables: {}
|
||||||
|
verify: false
|
||||||
|
teststeps:
|
||||||
|
- name: /get
|
||||||
|
request:
|
||||||
|
headers:
|
||||||
|
Accept-Encoding: gzip
|
||||||
|
Host: postman-echo.com
|
||||||
|
User-Agent: HttpRunnerPlus
|
||||||
|
method: GET
|
||||||
|
params:
|
||||||
|
foo1: HDnY8
|
||||||
|
foo2: '34.5'
|
||||||
|
url: https://postman-echo.com/get
|
||||||
|
validate:
|
||||||
|
- eq:
|
||||||
|
- status_code
|
||||||
|
- 200
|
||||||
|
- eq:
|
||||||
|
- headers.Content-Type
|
||||||
|
- application/json; charset=utf-8
|
||||||
|
- eq:
|
||||||
|
- body.url
|
||||||
|
- https://postman-echo.com/get?foo1=HDnY8&foo2=34.5
|
||||||
|
- name: /post
|
||||||
|
request:
|
||||||
|
cookies:
|
||||||
|
sails.sid: s%3Az_LpglkKxTvJ_eHVUH6V67drKp0AGWW-.PidabaXOnatLRP47hVyqqepl6BdrpEQzRlJQXtbIiwk
|
||||||
|
headers:
|
||||||
|
Accept-Encoding: gzip
|
||||||
|
Content-Length: '28'
|
||||||
|
Content-Type: application/json; charset=UTF-8
|
||||||
|
Cookie: sails.sid=s%3Az_LpglkKxTvJ_eHVUH6V67drKp0AGWW-.PidabaXOnatLRP47hVyqqepl6BdrpEQzRlJQXtbIiwk
|
||||||
|
Host: postman-echo.com
|
||||||
|
User-Agent: Go-http-client/1.1
|
||||||
|
json:
|
||||||
|
foo1: HDnY8
|
||||||
|
foo2: 12.3
|
||||||
|
method: POST
|
||||||
|
url: https://postman-echo.com/post
|
||||||
|
validate:
|
||||||
|
- eq:
|
||||||
|
- status_code
|
||||||
|
- 200
|
||||||
|
- eq:
|
||||||
|
- headers.Content-Type
|
||||||
|
- application/json; charset=utf-8
|
||||||
|
- eq:
|
||||||
|
- body.url
|
||||||
|
- https://postman-echo.com/post
|
||||||
|
- name: /post
|
||||||
|
request:
|
||||||
|
cookies:
|
||||||
|
sails.sid: s%3AS5e7w0zQ0xAsCwh9L8T6R7QLYCO7_gtD.r8%2B2w9IWqEIfuVkrZjnxzm2xADIk34zKAWXRPapr%2FAw
|
||||||
|
data:
|
||||||
|
foo1: HDnY8
|
||||||
|
foo2: '12.3'
|
||||||
|
headers:
|
||||||
|
Accept-Encoding: gzip
|
||||||
|
Content-Length: '20'
|
||||||
|
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
|
||||||
|
Cookie: sails.sid=s%3AS5e7w0zQ0xAsCwh9L8T6R7QLYCO7_gtD.r8%2B2w9IWqEIfuVkrZjnxzm2xADIk34zKAWXRPapr%2FAw
|
||||||
|
Host: postman-echo.com
|
||||||
|
User-Agent: Go-http-client/1.1
|
||||||
|
method: POST
|
||||||
|
url: https://postman-echo.com/post
|
||||||
|
validate:
|
||||||
|
- eq:
|
||||||
|
- status_code
|
||||||
|
- 200
|
||||||
|
- eq:
|
||||||
|
- headers.Content-Type
|
||||||
|
- application/json; charset=utf-8
|
||||||
|
- eq:
|
||||||
|
- body.data
|
||||||
|
- ''
|
||||||
|
- eq:
|
||||||
|
- body.url
|
||||||
|
- https://postman-echo.com/post
|
||||||
@@ -7,6 +7,8 @@ import (
|
|||||||
"github.com/httprunner/hrp/internal/builtin"
|
"github.com/httprunner/hrp/internal/builtin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const rendezvousTestJSONPath = "rendezvous_test.json"
|
||||||
|
|
||||||
var rendezvousTestcase = &hrp.TestCase{
|
var rendezvousTestcase = &hrp.TestCase{
|
||||||
Config: hrp.NewConfig("run request with functions").
|
Config: hrp.NewConfig("run request with functions").
|
||||||
SetBaseURL("https://postman-echo.com").
|
SetBaseURL("https://postman-echo.com").
|
||||||
@@ -59,7 +61,7 @@ func TestRendezvousDump2JSON(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("ToTCase error: %v", err)
|
t.Fatalf("ToTCase error: %v", err)
|
||||||
}
|
}
|
||||||
err = builtin.Dump2JSON(tCase, "rendezvous_test.json")
|
err = builtin.Dump2JSON(tCase, rendezvousTestJSONPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("dump to json error: %v", err)
|
t.Fatalf("dump to json error: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ func (h *har) prepareTestStep(entry *Entry) (*hrp.TStep, error) {
|
|||||||
step := &tStep{
|
step := &tStep{
|
||||||
TStep: hrp.TStep{
|
TStep: hrp.TStep{
|
||||||
Request: &hrp.Request{},
|
Request: &hrp.Request{},
|
||||||
Validators: make([]hrp.Validator, 0),
|
Validators: make([]interface{}, 0),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := step.makeRequestMethod(entry); err != nil {
|
if err := step.makeRequestMethod(entry); err != nil {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/httprunner/hrp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -98,13 +100,16 @@ func TestMakeTestCase(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make validators
|
// make validators
|
||||||
if !assert.Equal(t, "status_code", tCase.TestSteps[0].Validators[0].Check) {
|
validator, ok := tCase.TestSteps[0].Validators[0].(hrp.Validator)
|
||||||
|
if !ok || !assert.Equal(t, "status_code", validator.Check) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, "headers.\"Content-Type\"", tCase.TestSteps[0].Validators[1].Check) {
|
validator, ok = tCase.TestSteps[0].Validators[1].(hrp.Validator)
|
||||||
|
if !ok || !assert.Equal(t, "headers.\"Content-Type\"", validator.Check) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, "body.url", tCase.TestSteps[0].Validators[2].Check) {
|
validator, ok = tCase.TestSteps[0].Validators[2].(hrp.Validator)
|
||||||
|
if !ok || !assert.Equal(t, "body.url", validator.Check) {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
models.go
10
models.go
@@ -97,6 +97,8 @@ type Request struct {
|
|||||||
Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"`
|
Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||||
Cookies map[string]string `json:"cookies,omitempty" yaml:"cookies,omitempty"`
|
Cookies map[string]string `json:"cookies,omitempty" yaml:"cookies,omitempty"`
|
||||||
Body interface{} `json:"body,omitempty" yaml:"body,omitempty"`
|
Body interface{} `json:"body,omitempty" yaml:"body,omitempty"`
|
||||||
|
Json interface{} `json:"json,omitempty" yaml:"json,omitempty"`
|
||||||
|
Data interface{} `json:"data,omitempty" yaml:"data,omitempty"`
|
||||||
Timeout float32 `json:"timeout,omitempty" yaml:"timeout,omitempty"`
|
Timeout float32 `json:"timeout,omitempty" yaml:"timeout,omitempty"`
|
||||||
AllowRedirects bool `json:"allow_redirects,omitempty" yaml:"allow_redirects,omitempty"`
|
AllowRedirects bool `json:"allow_redirects,omitempty" yaml:"allow_redirects,omitempty"`
|
||||||
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
||||||
@@ -122,7 +124,7 @@ type TStep struct {
|
|||||||
SetupHooks []string `json:"setup_hooks,omitempty" yaml:"setup_hooks,omitempty"`
|
SetupHooks []string `json:"setup_hooks,omitempty" yaml:"setup_hooks,omitempty"`
|
||||||
TeardownHooks []string `json:"teardown_hooks,omitempty" yaml:"teardown_hooks,omitempty"`
|
TeardownHooks []string `json:"teardown_hooks,omitempty" yaml:"teardown_hooks,omitempty"`
|
||||||
Extract map[string]string `json:"extract,omitempty" yaml:"extract,omitempty"`
|
Extract map[string]string `json:"extract,omitempty" yaml:"extract,omitempty"`
|
||||||
Validators []Validator `json:"validate,omitempty" yaml:"validate,omitempty"`
|
Validators []interface{} `json:"validate,omitempty" yaml:"validate,omitempty"`
|
||||||
Export []string `json:"export,omitempty" yaml:"export,omitempty"`
|
Export []string `json:"export,omitempty" yaml:"export,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,11 +303,11 @@ type testCaseInOut struct {
|
|||||||
type testCaseSummary struct {
|
type testCaseSummary struct {
|
||||||
Name string `json:"name" yaml:"name"`
|
Name string `json:"name" yaml:"name"`
|
||||||
Success bool `json:"success" yaml:"success"`
|
Success bool `json:"success" yaml:"success"`
|
||||||
CaseId string `json:"case_id,omitempty" yaml:"case_id,omitempty"` //TODO
|
CaseId string `json:"case_id,omitempty" yaml:"case_id,omitempty"` // TODO
|
||||||
Stat *testStepStat `json:"stat" yaml:"stat"`
|
Stat *testStepStat `json:"stat" yaml:"stat"`
|
||||||
Time *testCaseTime `json:"time" yaml:"time"`
|
Time *testCaseTime `json:"time" yaml:"time"`
|
||||||
InOut *testCaseInOut `json:"in_out" yaml:"in_out"`
|
InOut *testCaseInOut `json:"in_out" yaml:"in_out"`
|
||||||
Log string `json:"log,omitempty" yaml:"log,omitempty"` //TODO
|
Log string `json:"log,omitempty" yaml:"log,omitempty"` // TODO
|
||||||
Records []*stepData `json:"records" yaml:"records"`
|
Records []*stepData `json:"records" yaml:"records"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +332,7 @@ type address struct {
|
|||||||
type SessionData struct {
|
type SessionData struct {
|
||||||
Success bool `json:"success" yaml:"success"`
|
Success bool `json:"success" yaml:"success"`
|
||||||
ReqResps *reqResps `json:"req_resps" yaml:"req_resps"`
|
ReqResps *reqResps `json:"req_resps" yaml:"req_resps"`
|
||||||
Address *address `json:"address,omitempty" yaml:"address,omitempty"` //TODO
|
Address *address `json:"address,omitempty" yaml:"address,omitempty"` // TODO
|
||||||
Validators []*validationResult `json:"validators,omitempty" yaml:"validators,omitempty"`
|
Validators []*validationResult `json:"validators,omitempty" yaml:"validators,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
response.go
12
response.go
@@ -114,8 +114,12 @@ func (v *responseObject) Extract(extractors map[string]string) map[string]interf
|
|||||||
return extractMapping
|
return extractMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *responseObject) Validate(validators []Validator, variablesMapping map[string]interface{}) (err error) {
|
func (v *responseObject) Validate(iValidators []interface{}, variablesMapping map[string]interface{}) (err error) {
|
||||||
for _, validator := range validators {
|
for _, iValidator := range iValidators {
|
||||||
|
validator, ok := iValidator.(Validator)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("validator type error")
|
||||||
|
}
|
||||||
// parse check value
|
// parse check value
|
||||||
checkItem := validator.Check
|
checkItem := validator.Check
|
||||||
var checkValue interface{}
|
var checkValue interface{}
|
||||||
@@ -160,6 +164,7 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s
|
|||||||
}
|
}
|
||||||
v.validationResults = append(v.validationResults, validResult)
|
v.validationResults = append(v.validationResults, validResult)
|
||||||
log.Info().
|
log.Info().
|
||||||
|
Str("checkExpr", validator.Check).
|
||||||
Str("assertMethod", assertMethod).
|
Str("assertMethod", assertMethod).
|
||||||
Interface("expectValue", expectValue).
|
Interface("expectValue", expectValue).
|
||||||
Interface("checkValue", checkValue).
|
Interface("checkValue", checkValue).
|
||||||
@@ -168,7 +173,8 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s
|
|||||||
if !result {
|
if !result {
|
||||||
v.t.Fail()
|
v.t.Fail()
|
||||||
return errors.New(fmt.Sprintf(
|
return errors.New(fmt.Sprintf(
|
||||||
"do assertion failed, assertMethod: %v, checkValue: %v, expectValue: %v",
|
"do assertion failed, checkExpr: %v, assertMethod: %v, checkValue: %v, expectValue: %v",
|
||||||
|
validator.Check,
|
||||||
assertMethod,
|
assertMethod,
|
||||||
checkValue,
|
checkValue,
|
||||||
expectValue,
|
expectValue,
|
||||||
|
|||||||
@@ -703,6 +703,15 @@ func (r *caseRunner) runStepRequest(step *TStep) (stepResult *stepData, err erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return stepResult, err
|
return stepResult, err
|
||||||
}
|
}
|
||||||
|
// check request body format if Content-Type specified as application/json
|
||||||
|
if strings.HasPrefix(req.Header.Get("Content-Type"), "application/json") {
|
||||||
|
switch data.(type) {
|
||||||
|
case bool, float64, string, map[string]interface{}, []interface{}, nil:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return stepResult, errors.Errorf("request body type inconsistent with Content-Type: %v", req.Header.Get("Content-Type"))
|
||||||
|
}
|
||||||
|
}
|
||||||
requestMap["body"] = data
|
requestMap["body"] = data
|
||||||
var dataBytes []byte
|
var dataBytes []byte
|
||||||
switch vv := data.(type) {
|
switch vv := data.(type) {
|
||||||
|
|||||||
@@ -42,7 +42,8 @@ func TestRunRequestGetToStruct(t *testing.T) {
|
|||||||
if tStep.Request.Cookies["user"] != "debugtalk" {
|
if tStep.Request.Cookies["user"] != "debugtalk" {
|
||||||
t.Fatalf("tStep.Request.Cookies mismatch")
|
t.Fatalf("tStep.Request.Cookies mismatch")
|
||||||
}
|
}
|
||||||
if tStep.Validators[0].Check != "status_code" || tStep.Validators[0].Expect != 200 {
|
validator, ok := tStep.Validators[0].(Validator)
|
||||||
|
if !ok || validator.Check != "status_code" || validator.Expect != 200 {
|
||||||
t.Fatalf("tStep.Validators mismatch")
|
t.Fatalf("tStep.Validators mismatch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,7 +68,8 @@ func TestRunRequestPostDataToStruct(t *testing.T) {
|
|||||||
if tStep.Request.Body != "a=1&b=2" {
|
if tStep.Request.Body != "a=1&b=2" {
|
||||||
t.Fatalf("tStep.Request.Data mismatch")
|
t.Fatalf("tStep.Request.Data mismatch")
|
||||||
}
|
}
|
||||||
if tStep.Validators[0].Check != "status_code" || tStep.Validators[0].Expect != 200 {
|
validator, ok := tStep.Validators[0].(Validator)
|
||||||
|
if !ok || validator.Check != "status_code" || validator.Expect != 200 {
|
||||||
t.Fatalf("tStep.Validators mismatch")
|
t.Fatalf("tStep.Validators mismatch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user