mirror of
https://github.com/httprunner/httprunner.git
synced 2026-08-04 13:06:57 +08:00
Merge branch 'master' of github.com:httprunner/httprunner
This commit is contained in:
@@ -1,12 +1,14 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
## v4.1.0 (2022-05-23)
|
## v4.1.0 (2022-05-25)
|
||||||
|
|
||||||
- feat: add `wiki` sub-command to open httprunner website
|
- feat: add `wiki` sub-command to open httprunner website
|
||||||
|
|
||||||
**go version**
|
**go version**
|
||||||
|
|
||||||
|
- fix #1308: load `.env` file as environment variables
|
||||||
- fix #1309: locate plugin file upward recursively until system root dir
|
- fix #1309: locate plugin file upward recursively until system root dir
|
||||||
|
- refactor: move base_url to config env
|
||||||
- feat: support converting Postman collection to HttpRunner testcase
|
- feat: support converting Postman collection to HttpRunner testcase
|
||||||
- refactor: improve the extensibility of `hrp convert` using interface `ICaseConverter`
|
- refactor: improve the extensibility of `hrp convert` using interface `ICaseConverter`
|
||||||
|
|
||||||
|
|||||||
@@ -35,5 +35,6 @@ Copyright 2017 debugtalk
|
|||||||
* [hrp pytest](hrp_pytest.md) - run API test with pytest
|
* [hrp pytest](hrp_pytest.md) - run API test with pytest
|
||||||
* [hrp run](hrp_run.md) - run API test with go engine
|
* [hrp run](hrp_run.md) - run API test with go engine
|
||||||
* [hrp startproject](hrp_startproject.md) - create a scaffold project
|
* [hrp startproject](hrp_startproject.md) - create a scaffold project
|
||||||
|
* [hrp wiki](hrp_wiki.md) - visit https://httprunner.com
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 23-May-2022
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
|
|||||||
@@ -42,4 +42,4 @@ hrp boom [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 23-May-2022
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ hrp convert $path... [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 23-May-2022
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
|
|||||||
@@ -24,4 +24,4 @@ hrp har2case $har_path... [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 23-May-2022
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
|
|||||||
@@ -16,4 +16,4 @@ hrp pytest $path ... [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 23-May-2022
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
|
|||||||
@@ -35,4 +35,4 @@ hrp run $path... [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 23-May-2022
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ hrp startproject $project_name [flags]
|
|||||||
|
|
||||||
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra on 23-May-2022
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
|
|||||||
19
docs/cmd/hrp_wiki.md
Normal file
19
docs/cmd/hrp_wiki.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
## hrp wiki
|
||||||
|
|
||||||
|
visit https://httprunner.com
|
||||||
|
|
||||||
|
```
|
||||||
|
hrp wiki [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for wiki
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [hrp](hrp.md) - Next-Generation API Testing Solution.
|
||||||
|
|
||||||
|
###### Auto generated by spf13/cobra on 25-May-2022
|
||||||
3
examples/demo-with-go-plugin/.env
Normal file
3
examples/demo-with-go-plugin/.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
base_url=https://postman-echo.com
|
||||||
|
USERNAME=debugtalk
|
||||||
|
PASSWORD=123456
|
||||||
1
examples/demo-with-go-plugin/.gitignore
vendored
1
examples/demo-with-go-plugin/.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
.env
|
|
||||||
reports/
|
reports/
|
||||||
*.so
|
*.so
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
6
examples/demo-with-go-plugin/proj.json
Normal file
6
examples/demo-with-go-plugin/proj.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"project_name": "demo-with-go-plugin",
|
||||||
|
"project_path": "/Users/debugtalk/MyProjects/HttpRunner-dev/httprunner/examples/demo-with-go-plugin",
|
||||||
|
"create_time": "2022-05-25T11:14:42.750876+08:00",
|
||||||
|
"hrp_version": "v4.1.0-beta"
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
{
|
{
|
||||||
"name": "get with params",
|
"name": "get with params",
|
||||||
"variables": {
|
"variables": {
|
||||||
"foo1": "bar11",
|
"foo1": "${ENV(USERNAME)}",
|
||||||
"foo2": "bar21",
|
"foo2": "bar21",
|
||||||
"sum_v": "${sum_two_int(1, 2)}"
|
"sum_v": "${sum_two_int(1, 2)}"
|
||||||
},
|
},
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
{
|
{
|
||||||
"eq": [
|
"eq": [
|
||||||
"body.args.foo1",
|
"body.args.foo1",
|
||||||
"bar11"
|
"debugtalk"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ config:
|
|||||||
foo2: config_bar2
|
foo2: config_bar2
|
||||||
expect_foo1: config_bar1
|
expect_foo1: config_bar1
|
||||||
expect_foo2: config_bar2
|
expect_foo2: config_bar2
|
||||||
base_url: "https://postman-echo.com"
|
|
||||||
verify: False
|
verify: False
|
||||||
export: ["foo3"]
|
export: ["foo3"]
|
||||||
|
|
||||||
@@ -13,12 +12,12 @@ teststeps:
|
|||||||
-
|
-
|
||||||
name: get with params
|
name: get with params
|
||||||
variables:
|
variables:
|
||||||
foo1: bar11
|
foo1: ${ENV(USERNAME)}
|
||||||
foo2: bar21
|
foo2: bar21
|
||||||
sum_v: "${sum_two_int(1, 2)}"
|
sum_v: "${sum_two_int(1, 2)}"
|
||||||
request:
|
request:
|
||||||
method: GET
|
method: GET
|
||||||
url: /get
|
url: $base_url/get
|
||||||
params:
|
params:
|
||||||
foo1: $foo1
|
foo1: $foo1
|
||||||
foo2: $foo2
|
foo2: $foo2
|
||||||
@@ -29,7 +28,7 @@ teststeps:
|
|||||||
foo3: "body.args.foo2"
|
foo3: "body.args.foo2"
|
||||||
validate:
|
validate:
|
||||||
- eq: ["status_code", 200]
|
- eq: ["status_code", 200]
|
||||||
- eq: ["body.args.foo1", "bar11"]
|
- eq: ["body.args.foo1", "debugtalk"]
|
||||||
- eq: ["body.args.sum_v", "3"]
|
- eq: ["body.args.sum_v", "3"]
|
||||||
- eq: ["body.args.foo2", "bar21"]
|
- eq: ["body.args.foo2", "bar21"]
|
||||||
-
|
-
|
||||||
@@ -39,7 +38,7 @@ teststeps:
|
|||||||
foo3: "bar32"
|
foo3: "bar32"
|
||||||
request:
|
request:
|
||||||
method: POST
|
method: POST
|
||||||
url: /post
|
url: $base_url/post
|
||||||
headers:
|
headers:
|
||||||
User-Agent: funplugin/${get_version()}
|
User-Agent: funplugin/${get_version()}
|
||||||
Content-Type: "text/plain"
|
Content-Type: "text/plain"
|
||||||
@@ -53,7 +52,7 @@ teststeps:
|
|||||||
foo2: bar23
|
foo2: bar23
|
||||||
request:
|
request:
|
||||||
method: POST
|
method: POST
|
||||||
url: /post
|
url: $base_url/post
|
||||||
headers:
|
headers:
|
||||||
User-Agent: funplugin/${get_version()}
|
User-Agent: funplugin/${get_version()}
|
||||||
Content-Type: "application/x-www-form-urlencoded"
|
Content-Type: "application/x-www-form-urlencoded"
|
||||||
|
|||||||
3
examples/demo-with-py-plugin/.env
Normal file
3
examples/demo-with-py-plugin/.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
base_url=https://postman-echo.com
|
||||||
|
USERNAME=debugtalk
|
||||||
|
PASSWORD=123456
|
||||||
1
examples/demo-with-py-plugin/.gitignore
vendored
1
examples/demo-with-py-plugin/.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
.env
|
|
||||||
reports/
|
reports/
|
||||||
*.so
|
*.so
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
6
examples/demo-with-py-plugin/proj.json
Normal file
6
examples/demo-with-py-plugin/proj.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"project_name": "demo-with-py-plugin",
|
||||||
|
"project_path": "/Users/debugtalk/MyProjects/HttpRunner-dev/httprunner/examples/demo-with-py-plugin",
|
||||||
|
"create_time": "2022-05-25T11:14:52.333942+08:00",
|
||||||
|
"hrp_version": "v4.1.0-beta"
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
{
|
{
|
||||||
"name": "get with params",
|
"name": "get with params",
|
||||||
"variables": {
|
"variables": {
|
||||||
"foo1": "bar11",
|
"foo1": "${ENV(USERNAME)}",
|
||||||
"foo2": "bar21",
|
"foo2": "bar21",
|
||||||
"sum_v": "${sum_two_int(1, 2)}"
|
"sum_v": "${sum_two_int(1, 2)}"
|
||||||
},
|
},
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
{
|
{
|
||||||
"eq": [
|
"eq": [
|
||||||
"body.args.foo1",
|
"body.args.foo1",
|
||||||
"bar11"
|
"debugtalk"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ config:
|
|||||||
foo2: config_bar2
|
foo2: config_bar2
|
||||||
expect_foo1: config_bar1
|
expect_foo1: config_bar1
|
||||||
expect_foo2: config_bar2
|
expect_foo2: config_bar2
|
||||||
base_url: "https://postman-echo.com"
|
|
||||||
verify: False
|
verify: False
|
||||||
export: ["foo3"]
|
export: ["foo3"]
|
||||||
|
|
||||||
@@ -13,12 +12,12 @@ teststeps:
|
|||||||
-
|
-
|
||||||
name: get with params
|
name: get with params
|
||||||
variables:
|
variables:
|
||||||
foo1: bar11
|
foo1: ${ENV(USERNAME)}
|
||||||
foo2: bar21
|
foo2: bar21
|
||||||
sum_v: "${sum_two_int(1, 2)}"
|
sum_v: "${sum_two_int(1, 2)}"
|
||||||
request:
|
request:
|
||||||
method: GET
|
method: GET
|
||||||
url: /get
|
url: $base_url/get
|
||||||
params:
|
params:
|
||||||
foo1: $foo1
|
foo1: $foo1
|
||||||
foo2: $foo2
|
foo2: $foo2
|
||||||
@@ -29,7 +28,7 @@ teststeps:
|
|||||||
foo3: "body.args.foo2"
|
foo3: "body.args.foo2"
|
||||||
validate:
|
validate:
|
||||||
- eq: ["status_code", 200]
|
- eq: ["status_code", 200]
|
||||||
- eq: ["body.args.foo1", "bar11"]
|
- eq: ["body.args.foo1", "debugtalk"]
|
||||||
- eq: ["body.args.sum_v", "3"]
|
- eq: ["body.args.sum_v", "3"]
|
||||||
- eq: ["body.args.foo2", "bar21"]
|
- eq: ["body.args.foo2", "bar21"]
|
||||||
-
|
-
|
||||||
@@ -39,7 +38,7 @@ teststeps:
|
|||||||
foo3: "bar32"
|
foo3: "bar32"
|
||||||
request:
|
request:
|
||||||
method: POST
|
method: POST
|
||||||
url: /post
|
url: $base_url/post
|
||||||
headers:
|
headers:
|
||||||
User-Agent: funplugin/${get_version()}
|
User-Agent: funplugin/${get_version()}
|
||||||
Content-Type: "text/plain"
|
Content-Type: "text/plain"
|
||||||
@@ -53,7 +52,7 @@ teststeps:
|
|||||||
foo2: bar23
|
foo2: bar23
|
||||||
request:
|
request:
|
||||||
method: POST
|
method: POST
|
||||||
url: /post
|
url: $base_url/post
|
||||||
headers:
|
headers:
|
||||||
User-Agent: funplugin/${get_version()}
|
User-Agent: funplugin/${get_version()}
|
||||||
Content-Type: "application/x-www-form-urlencoded"
|
Content-Type: "application/x-www-form-urlencoded"
|
||||||
|
|||||||
3
examples/demo-without-plugin/.env
Normal file
3
examples/demo-without-plugin/.env
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
base_url=https://postman-echo.com
|
||||||
|
USERNAME=debugtalk
|
||||||
|
PASSWORD=123456
|
||||||
1
examples/demo-without-plugin/.gitignore
vendored
1
examples/demo-without-plugin/.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
.env
|
|
||||||
reports/
|
reports/
|
||||||
*.so
|
*.so
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
6
examples/demo-without-plugin/proj.json
Normal file
6
examples/demo-without-plugin/proj.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"project_name": "demo-without-plugin",
|
||||||
|
"project_path": "/Users/debugtalk/MyProjects/HttpRunner-dev/httprunner/examples/demo-without-plugin",
|
||||||
|
"create_time": "2022-05-25T11:14:53.862348+08:00",
|
||||||
|
"hrp_version": "v4.1.0-beta"
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
func NewConfig(name string) *TConfig {
|
func NewConfig(name string) *TConfig {
|
||||||
return &TConfig{
|
return &TConfig{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Environs: make(map[string]string),
|
||||||
Variables: make(map[string]interface{}),
|
Variables: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,9 +20,10 @@ func NewConfig(name string) *TConfig {
|
|||||||
type TConfig struct {
|
type TConfig struct {
|
||||||
Name string `json:"name" yaml:"name"` // required
|
Name string `json:"name" yaml:"name"` // required
|
||||||
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
||||||
BaseURL string `json:"base_url,omitempty" yaml:"base_url,omitempty"`
|
BaseURL string `json:"base_url,omitempty" yaml:"base_url,omitempty"` // deprecated in v4.1, moved to env
|
||||||
Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"`
|
Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"` // public request headers
|
||||||
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"`
|
Environs map[string]string `json:"environs,omitempty" yaml:"environs,omitempty"` // environment variables
|
||||||
|
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"` // global variables
|
||||||
Parameters map[string]interface{} `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
Parameters map[string]interface{} `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||||
ParametersSetting *TParamsConfig `json:"parameters_setting,omitempty" yaml:"parameters_setting,omitempty"`
|
ParametersSetting *TParamsConfig `json:"parameters_setting,omitempty" yaml:"parameters_setting,omitempty"`
|
||||||
ThinkTimeSetting *ThinkTimeConfig `json:"think_time,omitempty" yaml:"think_time,omitempty"`
|
ThinkTimeSetting *ThinkTimeConfig `json:"think_time,omitempty" yaml:"think_time,omitempty"`
|
||||||
|
|||||||
@@ -295,12 +295,44 @@ func LoadFile(path string, structObj interface{}) (err error) {
|
|||||||
err = decoder.Decode(structObj)
|
err = decoder.Decode(structObj)
|
||||||
case ".yaml", ".yml":
|
case ".yaml", ".yml":
|
||||||
err = yaml.Unmarshal(file, structObj)
|
err = yaml.Unmarshal(file, structObj)
|
||||||
|
case ".env":
|
||||||
|
err = parseEnvContent(file, structObj)
|
||||||
default:
|
default:
|
||||||
err = ErrUnsupportedFileExt
|
err = ErrUnsupportedFileExt
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseEnvContent(file []byte, obj interface{}) error {
|
||||||
|
envMap := obj.(map[string]string)
|
||||||
|
lines := strings.Split(string(file), "\n")
|
||||||
|
for _, line := range lines {
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
|
// empty line or comment line
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var kv []string
|
||||||
|
if strings.Contains(line, "=") {
|
||||||
|
kv = strings.SplitN(line, "=", 2)
|
||||||
|
} else if strings.Contains(line, ":") {
|
||||||
|
kv = strings.SplitN(line, ":", 2)
|
||||||
|
}
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return errors.New(".env format error")
|
||||||
|
}
|
||||||
|
|
||||||
|
key := strings.TrimSpace(kv[0])
|
||||||
|
value := strings.TrimSpace(kv[1])
|
||||||
|
envMap[key] = value
|
||||||
|
|
||||||
|
// set env
|
||||||
|
log.Info().Str("key", key).Msg("set env")
|
||||||
|
os.Setenv(key, value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadFromCSV(path string) []map[string]interface{} {
|
func loadFromCSV(path string) []map[string]interface{} {
|
||||||
log.Info().Str("path", path).Msg("load csv file")
|
log.Info().Str("path", path).Msg("load csv file")
|
||||||
file, err := readFile(path)
|
file, err := readFile(path)
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ func CreateScaffold(projectName string, pluginType PluginType, force bool) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
projectInfo := &ProjectInfo{
|
projectInfo := &ProjectInfo{
|
||||||
ProjectName: projectName,
|
ProjectName: filepath.Base(projectName),
|
||||||
ProjectPath: projectPath,
|
ProjectPath: projectPath,
|
||||||
CreateTime: time.Now(),
|
CreateTime: time.Now(),
|
||||||
Version: version.VERSION,
|
Version: version.VERSION,
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
|
base_url=https://postman-echo.com
|
||||||
USERNAME=debugtalk
|
USERNAME=debugtalk
|
||||||
PASSWORD=123456
|
PASSWORD=123456
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
.env
|
|
||||||
reports/
|
reports/
|
||||||
*.so
|
*.so
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
{
|
{
|
||||||
"name": "get with params",
|
"name": "get with params",
|
||||||
"variables": {
|
"variables": {
|
||||||
"foo1": "bar11",
|
"foo1": "${ENV(USERNAME)}",
|
||||||
"foo2": "bar21",
|
"foo2": "bar21",
|
||||||
"sum_v": "${sum_two_int(1, 2)}"
|
"sum_v": "${sum_two_int(1, 2)}"
|
||||||
},
|
},
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
{
|
{
|
||||||
"eq": [
|
"eq": [
|
||||||
"body.args.foo1",
|
"body.args.foo1",
|
||||||
"bar11"
|
"debugtalk"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ config:
|
|||||||
foo2: config_bar2
|
foo2: config_bar2
|
||||||
expect_foo1: config_bar1
|
expect_foo1: config_bar1
|
||||||
expect_foo2: config_bar2
|
expect_foo2: config_bar2
|
||||||
base_url: "https://postman-echo.com"
|
|
||||||
verify: False
|
verify: False
|
||||||
export: ["foo3"]
|
export: ["foo3"]
|
||||||
|
|
||||||
@@ -13,12 +12,12 @@ teststeps:
|
|||||||
-
|
-
|
||||||
name: get with params
|
name: get with params
|
||||||
variables:
|
variables:
|
||||||
foo1: bar11
|
foo1: ${ENV(USERNAME)}
|
||||||
foo2: bar21
|
foo2: bar21
|
||||||
sum_v: "${sum_two_int(1, 2)}"
|
sum_v: "${sum_two_int(1, 2)}"
|
||||||
request:
|
request:
|
||||||
method: GET
|
method: GET
|
||||||
url: /get
|
url: $base_url/get
|
||||||
params:
|
params:
|
||||||
foo1: $foo1
|
foo1: $foo1
|
||||||
foo2: $foo2
|
foo2: $foo2
|
||||||
@@ -29,7 +28,7 @@ teststeps:
|
|||||||
foo3: "body.args.foo2"
|
foo3: "body.args.foo2"
|
||||||
validate:
|
validate:
|
||||||
- eq: ["status_code", 200]
|
- eq: ["status_code", 200]
|
||||||
- eq: ["body.args.foo1", "bar11"]
|
- eq: ["body.args.foo1", "debugtalk"]
|
||||||
- eq: ["body.args.sum_v", "3"]
|
- eq: ["body.args.sum_v", "3"]
|
||||||
- eq: ["body.args.foo2", "bar21"]
|
- eq: ["body.args.foo2", "bar21"]
|
||||||
-
|
-
|
||||||
@@ -39,7 +38,7 @@ teststeps:
|
|||||||
foo3: "bar32"
|
foo3: "bar32"
|
||||||
request:
|
request:
|
||||||
method: POST
|
method: POST
|
||||||
url: /post
|
url: $base_url/post
|
||||||
headers:
|
headers:
|
||||||
User-Agent: funplugin/${get_version()}
|
User-Agent: funplugin/${get_version()}
|
||||||
Content-Type: "text/plain"
|
Content-Type: "text/plain"
|
||||||
@@ -53,7 +52,7 @@ teststeps:
|
|||||||
foo2: bar23
|
foo2: bar23
|
||||||
request:
|
request:
|
||||||
method: POST
|
method: POST
|
||||||
url: /post
|
url: $base_url/post
|
||||||
headers:
|
headers:
|
||||||
User-Agent: funplugin/${get_version()}
|
User-Agent: funplugin/${get_version()}
|
||||||
Content-Type: "application/x-www-form-urlencoded"
|
Content-Type: "application/x-www-form-urlencoded"
|
||||||
|
|||||||
@@ -287,6 +287,25 @@ func (r *testCaseRunner) parseConfig() error {
|
|||||||
}
|
}
|
||||||
r.parsedConfig.BaseURL = convertString(parsedBaseURL)
|
r.parsedConfig.BaseURL = convertString(parsedBaseURL)
|
||||||
|
|
||||||
|
// merge config environment variables with base_url
|
||||||
|
// priority: env base_url > base_url
|
||||||
|
if cfg.Environs != nil {
|
||||||
|
r.parsedConfig.Environs = cfg.Environs
|
||||||
|
} else {
|
||||||
|
r.parsedConfig.Environs = make(map[string]string)
|
||||||
|
}
|
||||||
|
if value, ok := r.parsedConfig.Environs["base_url"]; !ok || value == "" {
|
||||||
|
if r.parsedConfig.BaseURL != "" {
|
||||||
|
r.parsedConfig.Environs["base_url"] = r.parsedConfig.BaseURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// merge config variables with environment variables
|
||||||
|
// priority: env > config variables
|
||||||
|
for k, v := range r.parsedConfig.Environs {
|
||||||
|
r.parsedConfig.Variables[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
// ensure correction of think time config
|
// ensure correction of think time config
|
||||||
r.parsedConfig.ThinkTimeSetting.checkThinkTime()
|
r.parsedConfig.ThinkTimeSetting.checkThinkTime()
|
||||||
|
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ func (r *requestBuilder) prepareUrlParams(stepVariables map[string]interface{})
|
|||||||
log.Error().Err(err).Msg("parse request url failed")
|
log.Error().Err(err).Msg("parse request url failed")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rawUrl := buildURL(r.config.BaseURL, convertString(requestUrl))
|
baseURL := stepVariables["base_url"].(string)
|
||||||
|
rawUrl := buildURL(baseURL, convertString(requestUrl))
|
||||||
|
|
||||||
// prepare request params
|
// prepare request params
|
||||||
var queryParams url.Values
|
var queryParams url.Values
|
||||||
|
|||||||
@@ -80,6 +80,25 @@ func (path *TestCasePath) ToTestCase() (*TestCase, error) {
|
|||||||
return nil, errors.Wrap(err, "failed to get project root dir")
|
return nil, errors.Wrap(err, "failed to get project root dir")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load .env file
|
||||||
|
dotEnvPath := filepath.Join(projectRootDir, ".env")
|
||||||
|
if builtin.IsFilePathExists(dotEnvPath) {
|
||||||
|
envVars := make(map[string]string)
|
||||||
|
err = builtin.LoadFile(dotEnvPath, envVars)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to load .env file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// override testcase config env with variables loaded from .env file
|
||||||
|
// priority: .env file > testcase config env
|
||||||
|
if testCase.Config.Environs == nil {
|
||||||
|
testCase.Config.Environs = make(map[string]string)
|
||||||
|
}
|
||||||
|
for key, value := range envVars {
|
||||||
|
testCase.Config.Environs[key] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, step := range tc.TestSteps {
|
for _, step := range tc.TestSteps {
|
||||||
if step.API != nil {
|
if step.API != nil {
|
||||||
apiPath, ok := step.API.(string)
|
apiPath, ok := step.API.(string)
|
||||||
|
|||||||
@@ -307,7 +307,7 @@ class MyJSONEncoder(json.JSONEncoder):
|
|||||||
chunks = self.iterencode(o, _one_shot=True)
|
chunks = self.iterencode(o, _one_shot=True)
|
||||||
if not isinstance(chunks, (list, tuple)):
|
if not isinstance(chunks, (list, tuple)):
|
||||||
chunks = list(chunks)
|
chunks = list(chunks)
|
||||||
# add by braver(braver@bytedance.com)
|
# add by braver
|
||||||
# todo: fix 'utf8' codec can't decode byte 0x91 in position 3: invalid start byte"
|
# todo: fix 'utf8' codec can't decode byte 0x91 in position 3: invalid start byte"
|
||||||
if self.skip_nonutf8_value: # 缺省为false
|
if self.skip_nonutf8_value: # 缺省为false
|
||||||
tmp_chunks = []
|
tmp_chunks = []
|
||||||
@@ -324,7 +324,7 @@ class MyJSONEncoder(json.JSONEncoder):
|
|||||||
|
|
||||||
class ThriftJSONEncoder(json.JSONEncoder):
|
class ThriftJSONEncoder(json.JSONEncoder):
|
||||||
"""
|
"""
|
||||||
add by braver(Braver@bytedance.com)
|
add by braver
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -377,7 +377,7 @@ class ThriftJSONEncoder(json.JSONEncoder):
|
|||||||
chunks = self.iterencode(o, _one_shot=True)
|
chunks = self.iterencode(o, _one_shot=True)
|
||||||
if not isinstance(chunks, (list, tuple)):
|
if not isinstance(chunks, (list, tuple)):
|
||||||
chunks = list(chunks)
|
chunks = list(chunks)
|
||||||
# add by braver(braver@bytedance.com)
|
# add by braver
|
||||||
# todo: fix 'utf8' codec can't decode byte 0x91 in position 3: invalid start byte"
|
# todo: fix 'utf8' codec can't decode byte 0x91 in position 3: invalid start byte"
|
||||||
if self.skip_nonutf8_value: # 缺省为false
|
if self.skip_nonutf8_value: # 缺省为false
|
||||||
tmp_chunks = []
|
tmp_chunks = []
|
||||||
|
|||||||
Reference in New Issue
Block a user