mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 11:29:48 +08:00
feat: dump2YAML
This commit is contained in:
31
convert.go
31
convert.go
@@ -1,10 +1,13 @@
|
||||
package httpboomer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func (tc *TestCase) toStruct() *TCase {
|
||||
@@ -33,3 +36,31 @@ func (tc *TestCase) dump2JSON(path string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tc *TestCase) dump2YAML(path string) error {
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
log.Printf("convert absolute path error: %v, path: %v", err, path)
|
||||
return err
|
||||
}
|
||||
log.Printf("dump testcase to yaml path: %s", path)
|
||||
|
||||
// init yaml encoder
|
||||
buffer := new(bytes.Buffer)
|
||||
encoder := yaml.NewEncoder(buffer)
|
||||
encoder.SetIndent(4)
|
||||
|
||||
// encode
|
||||
tcStruct := tc.toStruct()
|
||||
err = encoder.Encode(tcStruct)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(path, buffer.Bytes(), 0644)
|
||||
if err != nil {
|
||||
log.Printf("dump yaml path error: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,50 +6,58 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var demoTestCase = &TestCase{
|
||||
Config: TConfig{
|
||||
Name: "demo with complex mechanisms",
|
||||
BaseURL: "https://postman-echo.com",
|
||||
Variables: map[string]interface{}{ // global level variables
|
||||
"n": 5,
|
||||
"a": 12.3,
|
||||
"b": 3.45,
|
||||
"varFoo1": "${gen_random_string($n)}",
|
||||
"varFoo2": "${max($a, $b)}", // 12.3; eval with built-in function
|
||||
},
|
||||
},
|
||||
TestSteps: []IStep{
|
||||
Step("get with params").
|
||||
WithVariables(map[string]interface{}{ // step level variables
|
||||
"n": 3, // inherit config level variables if not set in step level, a/varFoo1
|
||||
"b": 34.5, // override config level variable if existed, n/b/varFoo2
|
||||
"varFoo2": "${max($a, $b)}", // 34.5; override variable b and eval again
|
||||
}).
|
||||
GET("/get").
|
||||
WithParams(map[string]interface{}{"foo1": "$varFoo1", "foo2": "$varFoo2"}). // request with params
|
||||
WithHeaders(map[string]string{"User-Agent": "HttpBoomer"}). // request with headers
|
||||
Extract().
|
||||
WithJmesPath("body.args.foo1", "varFoo1"). // extract variable with jmespath
|
||||
Validate().
|
||||
AssertEqual("status_code", 200, "check response status code"). // validate response status code
|
||||
AssertStartsWith("headers.\"Content-Type\"", "application/json", ""). // validate response header
|
||||
AssertLengthEqual("body.args.foo1", 5, "check args foo1"). // validate response body with jmespath
|
||||
AssertLengthEqual("$varFoo1", 5, "check args foo1"). // assert with extracted variable from current step
|
||||
AssertEqual("body.args.foo2", "34.5", "check args foo2"), // notice: request params value will be converted to string
|
||||
Step("post json data").
|
||||
POST("/post").
|
||||
WithJSON(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
|
||||
}).
|
||||
Validate().
|
||||
AssertEqual("status_code", 200, "check status code").
|
||||
AssertLengthEqual("body.json.foo1", 5, "check args foo1").
|
||||
AssertEqual("body.json.foo2", 12.3, "check args foo2"),
|
||||
},
|
||||
}
|
||||
|
||||
func TestDump2JSON(t *testing.T) {
|
||||
testcase := &TestCase{
|
||||
Config: TConfig{
|
||||
Name: "demo with complex mechanisms",
|
||||
BaseURL: "https://postman-echo.com",
|
||||
Variables: map[string]interface{}{ // global level variables
|
||||
"n": 5,
|
||||
"a": 12.3,
|
||||
"b": 3.45,
|
||||
"varFoo1": "${gen_random_string($n)}",
|
||||
"varFoo2": "${max($a, $b)}", // 12.3; eval with built-in function
|
||||
},
|
||||
},
|
||||
TestSteps: []IStep{
|
||||
Step("get with params").
|
||||
WithVariables(map[string]interface{}{ // step level variables
|
||||
"n": 3, // inherit config level variables if not set in step level, a/varFoo1
|
||||
"b": 34.5, // override config level variable if existed, n/b/varFoo2
|
||||
"varFoo2": "${max($a, $b)}", // 34.5; override variable b and eval again
|
||||
}).
|
||||
GET("/get").
|
||||
WithParams(map[string]interface{}{"foo1": "$varFoo1", "foo2": "$varFoo2"}). // request with params
|
||||
WithHeaders(map[string]string{"User-Agent": "HttpBoomer"}). // request with headers
|
||||
Extract().
|
||||
WithJmesPath("body.args.foo1", "varFoo1"). // extract variable with jmespath
|
||||
Validate().
|
||||
AssertEqual("status_code", 200, "check response status code"). // validate response status code
|
||||
AssertStartsWith("headers.\"Content-Type\"", "application/json", ""). // validate response header
|
||||
AssertLengthEqual("body.args.foo1", 5, "check args foo1"). // validate response body with jmespath
|
||||
AssertLengthEqual("$varFoo1", 5, "check args foo1"). // assert with extracted variable from current step
|
||||
AssertEqual("body.args.foo2", "34.5", "check args foo2"), // notice: request params value will be converted to string
|
||||
Step("post json data").
|
||||
POST("/post").
|
||||
WithJSON(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
|
||||
}).
|
||||
Validate().
|
||||
AssertEqual("status_code", 200, "check status code").
|
||||
AssertLengthEqual("body.json.foo1", 5, "check args foo1").
|
||||
AssertEqual("body.json.foo2", 12.3, "check args foo2"),
|
||||
},
|
||||
}
|
||||
err := testcase.dump2JSON("test.json")
|
||||
err := demoTestCase.dump2JSON("demo.json")
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestDump2YAML(t *testing.T) {
|
||||
err := demoTestCase.dump2YAML("demo.yml")
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -20,4 +20,5 @@ require (
|
||||
github.com/zeromq/gomq v0.0.0-20201031135124-cef4e507bb8e // indirect
|
||||
github.com/zeromq/gomq/zmtp v0.0.0-20201031135124-cef4e507bb8e // indirect
|
||||
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
||||
|
||||
64
models.go
64
models.go
@@ -13,51 +13,51 @@ const (
|
||||
)
|
||||
|
||||
type TConfig struct {
|
||||
Name string `json:"name"`
|
||||
Verify bool `json:"verify,omitempty"`
|
||||
BaseURL string `json:"base_url,omitempty"`
|
||||
Variables map[string]interface{} `json:"variables,omitempty"`
|
||||
Parameters map[string]interface{} `json:"parameters,omitempty"`
|
||||
Export []string `json:"export,omitempty"`
|
||||
Weight int `json:"weight,omitempty"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
||||
BaseURL string `json:"base_url,omitempty" yaml:"base_url,omitempty"`
|
||||
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
Parameters map[string]interface{} `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Export []string `json:"export,omitempty" yaml:"export,omitempty"`
|
||||
Weight int `json:"weight,omitempty" yaml:"weight,omitempty"`
|
||||
}
|
||||
|
||||
type TRequest struct {
|
||||
Method enumHTTPMethod `json:"method"`
|
||||
URL string `json:"url"`
|
||||
Params map[string]interface{} `json:"params,omitempty"`
|
||||
Headers map[string]string `json:"headers,omitempty"`
|
||||
Cookies map[string]string `json:"cookies,omitempty"`
|
||||
Data interface{} `json:"data,omitempty"`
|
||||
JSON interface{} `json:"json,omitempty"`
|
||||
Timeout float32 `json:"timeout,omitempty"`
|
||||
AllowRedirects bool `json:"allow_redirects,omitempty"`
|
||||
Verify bool `json:"verify,omitempty"`
|
||||
Method enumHTTPMethod `json:"method" yaml:"method"`
|
||||
URL string `json:"url" yaml:"url"`
|
||||
Params map[string]interface{} `json:"params,omitempty" yaml:"params,omitempty"`
|
||||
Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Cookies map[string]string `json:"cookies,omitempty" yaml:"cookies,omitempty"`
|
||||
Data interface{} `json:"data,omitempty" yaml:"data,omitempty"`
|
||||
JSON interface{} `json:"json,omitempty" yaml:"json,omitempty"`
|
||||
Timeout float32 `json:"timeout,omitempty" yaml:"timeout,omitempty"`
|
||||
AllowRedirects bool `json:"allow_redirects,omitempty" yaml:"allow_redirects,omitempty"`
|
||||
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
||||
}
|
||||
|
||||
type TValidator struct {
|
||||
Check string `json:"check,omitempty"` // get value with jmespath
|
||||
Assert string `json:"assert,omitempty"`
|
||||
Expect interface{} `json:"expect,omitempty"`
|
||||
Message string `json:"msg,omitempty"`
|
||||
Check string `json:"check,omitempty" yaml:"check,omitempty"` // get value with jmespath
|
||||
Assert string `json:"assert,omitempty" yaml:"assert,omitempty"`
|
||||
Expect interface{} `json:"expect,omitempty" yaml:"expect,omitempty"`
|
||||
Message string `json:"msg,omitempty" yaml:"msg,omitempty"`
|
||||
}
|
||||
|
||||
type TStep struct {
|
||||
Name string `json:"name"`
|
||||
Request *TRequest `json:"request,omitempty"`
|
||||
TestCase *TestCase `json:"testcase,omitempty"`
|
||||
Variables map[string]interface{} `json:"variables,omitempty"`
|
||||
SetupHooks []string `json:"setup_hooks,omitempty"`
|
||||
TeardownHooks []string `json:"teardown_hooks,omitempty"`
|
||||
Extract map[string]string `json:"extract,omitempty"`
|
||||
Validators []TValidator `json:"validate,omitempty"`
|
||||
Export []string `json:"export,omitempty"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Request *TRequest `json:"request,omitempty" yaml:"request,omitempty"`
|
||||
TestCase *TestCase `json:"testcase,omitempty" yaml:"testcase,omitempty"`
|
||||
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
SetupHooks []string `json:"setup_hooks,omitempty" yaml:"setup_hooks,omitempty"`
|
||||
TeardownHooks []string `json:"teardown_hooks,omitempty" yaml:"teardown_hooks,omitempty"`
|
||||
Extract map[string]string `json:"extract,omitempty" yaml:"extract,omitempty"`
|
||||
Validators []TValidator `json:"validate,omitempty" yaml:"validate,omitempty"`
|
||||
Export []string `json:"export,omitempty" yaml:"export,omitempty"`
|
||||
}
|
||||
|
||||
// used for testcase json loading and dumping
|
||||
type TCase struct {
|
||||
Config TConfig `json:"config"`
|
||||
TestSteps []*TStep `json:"teststeps"`
|
||||
Config TConfig `json:"config" yaml:"config"`
|
||||
TestSteps []*TStep `json:"teststeps" yaml:"teststeps"`
|
||||
}
|
||||
|
||||
// interface for all types of steps
|
||||
|
||||
Reference in New Issue
Block a user