mirror of
https://github.com/httprunner/httprunner.git
synced 2026-08-09 15:53:21 +08:00
fix: call referenced api/testcase with relative path
This commit is contained in:
@@ -2,9 +2,11 @@ package hrp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/httprunner/httprunner/hrp/internal/builtin"
|
||||
@@ -92,9 +94,21 @@ func (tc *TCase) ToTestCase() (*TestCase, error) {
|
||||
testCase := &TestCase{
|
||||
Config: tc.Config,
|
||||
}
|
||||
|
||||
// locate project root dir by plugin path
|
||||
projectRootDir, err := getProjectRootDirPath(testCase.Config.Path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get project root dir")
|
||||
}
|
||||
log.Info().Str("dir", projectRootDir).Msg("located project root dir")
|
||||
|
||||
for _, step := range tc.TestSteps {
|
||||
if step.APIPath != "" {
|
||||
path := filepath.Join(filepath.Dir(testCase.Config.Path), step.APIPath)
|
||||
path := filepath.Join(projectRootDir, step.APIPath)
|
||||
if !builtin.IsFilePathExists(path) {
|
||||
return nil, errors.New("referenced api file not found: " + path)
|
||||
}
|
||||
|
||||
refAPI := APIPath(path)
|
||||
step.APIContent = &refAPI
|
||||
apiContent, err := step.APIContent.ToAPI()
|
||||
@@ -106,7 +120,11 @@ func (tc *TCase) ToTestCase() (*TestCase, error) {
|
||||
step: step,
|
||||
})
|
||||
} else if step.TestCasePath != "" {
|
||||
path := filepath.Join(filepath.Dir(testCase.Config.Path), step.TestCasePath)
|
||||
path := filepath.Join(projectRootDir, step.TestCasePath)
|
||||
if !builtin.IsFilePathExists(path) {
|
||||
return nil, errors.New("referenced testcase file not found: " + path)
|
||||
}
|
||||
|
||||
refTestCase := TestCasePath(path)
|
||||
step.TestCaseContent = &refTestCase
|
||||
tc, err := step.TestCaseContent.ToTestCase()
|
||||
@@ -140,16 +158,29 @@ func (tc *TCase) ToTestCase() (*TestCase, error) {
|
||||
return testCase, nil
|
||||
}
|
||||
|
||||
func getProjectRootDirPath(path string) (rootDir string, err error) {
|
||||
pluginPath, err := locatePlugin(path)
|
||||
if err == nil {
|
||||
rootDir = filepath.Dir(pluginPath)
|
||||
return
|
||||
}
|
||||
|
||||
// failed to locate project root dir
|
||||
// maybe project plugin debugtalk.xx is not exist
|
||||
// use current dir instead
|
||||
return os.Getwd()
|
||||
}
|
||||
|
||||
// APIPath implements IAPI interface.
|
||||
type APIPath string
|
||||
|
||||
func (path *APIPath) ToString() string {
|
||||
func (path *APIPath) GetPath() string {
|
||||
return fmt.Sprintf("%v", *path)
|
||||
}
|
||||
|
||||
func (path *APIPath) ToAPI() (*API, error) {
|
||||
api := &API{}
|
||||
apiPath := path.ToString()
|
||||
apiPath := path.GetPath()
|
||||
err := builtin.LoadFile(apiPath, api)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -161,22 +192,23 @@ func (path *APIPath) ToAPI() (*API, error) {
|
||||
// TestCasePath implements ITestCase interface.
|
||||
type TestCasePath string
|
||||
|
||||
func (path *TestCasePath) ToString() string {
|
||||
func (path *TestCasePath) GetPath() string {
|
||||
return fmt.Sprintf("%v", *path)
|
||||
}
|
||||
|
||||
func (path *TestCasePath) ToTestCase() (*TestCase, error) {
|
||||
tc := &TCase{}
|
||||
casePath := path.ToString()
|
||||
casePath := path.GetPath()
|
||||
err := builtin.LoadFile(casePath, tc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = convertCompatTestCase(tc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tc.Config.Path = path.ToString()
|
||||
tc.Config.Path = casePath
|
||||
testcase, err := tc.ToTestCase()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -8,20 +8,22 @@ import (
|
||||
"github.com/httprunner/httprunner/hrp/internal/builtin"
|
||||
)
|
||||
|
||||
const templatesDir = "internal/scaffold/templates/"
|
||||
const (
|
||||
templatesDir = "internal/scaffold/templates/"
|
||||
hrpExamplesDir = "../examples/hrp"
|
||||
)
|
||||
|
||||
var (
|
||||
demoTestCaseWithPluginJSONPath TestCasePath = templatesDir + "testcases/demo_with_funplugin.json"
|
||||
demoTestCaseWithPluginYAMLPath TestCasePath = templatesDir + "testcases/demo_with_funplugin.yaml"
|
||||
demoTestCaseWithoutPluginJSONPath TestCasePath = templatesDir + "testcases/demo_without_funplugin.json"
|
||||
demoTestCaseWithoutPluginYAMLPath TestCasePath = templatesDir + "testcases/demo_without_funplugin.yaml"
|
||||
demoTestCaseWithRefAPIPath TestCasePath = templatesDir + "testcases/demo_ref_api.json"
|
||||
demoAPIGETPath APIPath = templatesDir + "/api/get.yml"
|
||||
)
|
||||
|
||||
var (
|
||||
demoRefAPIYAMLPath TestCasePath = "../examples/hrp/ref_api_test.yaml"
|
||||
demoRefTestCaseJSONPath TestCasePath = "../examples/hrp/ref_testcase_test.json"
|
||||
demoThinkTimeJsonPath TestCasePath = "../examples/hrp/think_time_test.json"
|
||||
demoAPIYAMLPath APIPath = "../examples/hrp/api/put.yml"
|
||||
demoTestCaseWithThinkTimePath TestCasePath = hrpExamplesDir + "/think_time_test.json"
|
||||
)
|
||||
|
||||
var demoTestCaseWithPlugin = &TestCase{
|
||||
@@ -152,41 +154,21 @@ var demoTestCaseWithoutPlugin = &TestCase{
|
||||
|
||||
func TestGenDemoTestCase(t *testing.T) {
|
||||
tCase, _ := demoTestCaseWithPlugin.ToTCase()
|
||||
err := builtin.Dump2JSON(tCase, demoTestCaseWithPluginJSONPath.ToString())
|
||||
err := builtin.Dump2JSON(tCase, demoTestCaseWithPluginJSONPath.GetPath())
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
err = builtin.Dump2YAML(tCase, demoTestCaseWithPluginYAMLPath.ToString())
|
||||
err = builtin.Dump2YAML(tCase, demoTestCaseWithPluginYAMLPath.GetPath())
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
tCase, _ = demoTestCaseWithoutPlugin.ToTCase()
|
||||
err = builtin.Dump2JSON(tCase, demoTestCaseWithoutPluginJSONPath.ToString())
|
||||
err = builtin.Dump2JSON(tCase, demoTestCaseWithoutPluginJSONPath.GetPath())
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
err = builtin.Dump2YAML(tCase, demoTestCaseWithoutPluginYAMLPath.ToString())
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonDemoWithPlugin(t *testing.T) {
|
||||
buildHashicorpGoPlugin()
|
||||
defer removeHashicorpGoPlugin()
|
||||
|
||||
err := NewRunner(nil).Run(&demoTestCaseWithPluginJSONPath) // hrp.Run(testCase)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestYamlDemoWithPlugin(t *testing.T) {
|
||||
buildHashicorpGoPlugin()
|
||||
defer removeHashicorpGoPlugin()
|
||||
|
||||
err := NewRunner(nil).Run(&demoTestCaseWithPluginYAMLPath) // hrp.Run(testCase)
|
||||
err = builtin.Dump2YAML(tCase, demoTestCaseWithoutPluginYAMLPath.GetPath())
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
@@ -195,11 +177,11 @@ func TestYamlDemoWithPlugin(t *testing.T) {
|
||||
func TestLoadCase(t *testing.T) {
|
||||
tcJSON := &TCase{}
|
||||
tcYAML := &TCase{}
|
||||
err := builtin.LoadFile(demoTestCaseWithPluginJSONPath.ToString(), tcJSON)
|
||||
err := builtin.LoadFile(demoTestCaseWithPluginJSONPath.GetPath(), tcJSON)
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fail()
|
||||
}
|
||||
err = builtin.LoadFile(demoTestCaseWithPluginYAMLPath.ToString(), tcYAML)
|
||||
err = builtin.LoadFile(demoTestCaseWithPluginYAMLPath.GetPath(), tcYAML)
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fail()
|
||||
}
|
||||
@@ -218,7 +200,7 @@ func TestLoadCase(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_convertCheckExpr(t *testing.T) {
|
||||
func TestConvertCheckExpr(t *testing.T) {
|
||||
exprs := []struct {
|
||||
before string
|
||||
after string
|
||||
|
||||
@@ -108,16 +108,16 @@ func CreateFile(filePath string, data string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// isFilePathExists returns true if path exists, whether path is file or dir
|
||||
func isPathExists(path string) bool {
|
||||
// IsPathExists returns true if path exists, whether path is file or dir
|
||||
func IsPathExists(path string) bool {
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// isFilePathExists returns true if path exists and path is file
|
||||
func isFilePathExists(path string) bool {
|
||||
// IsFilePathExists returns true if path exists and path is file
|
||||
func IsFilePathExists(path string) bool {
|
||||
info, err := os.Stat(path)
|
||||
if err != nil {
|
||||
// path not exists
|
||||
@@ -133,10 +133,10 @@ func isFilePathExists(path string) bool {
|
||||
}
|
||||
|
||||
func EnsureFolderExists(folderPath string) error {
|
||||
if !isPathExists(folderPath) {
|
||||
if !IsPathExists(folderPath) {
|
||||
err := CreateFolder(folderPath)
|
||||
return err
|
||||
} else if isFilePathExists(folderPath) {
|
||||
} else if IsFilePathExists(folderPath) {
|
||||
return fmt.Errorf("path %v should be directory", folderPath)
|
||||
}
|
||||
return nil
|
||||
|
||||
34
hrp/internal/scaffold/templates/api/get.json
Normal file
34
hrp/internal/scaffold/templates/api/get.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"url": "/get",
|
||||
"params": {
|
||||
"foo1": "bar1",
|
||||
"foo2": "bar2"
|
||||
},
|
||||
"headers": {
|
||||
"Postman-Token": "ea19464c-ddd4-4724-abe9-5e2b254c2723"
|
||||
}
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "status_code",
|
||||
"assert": "equals",
|
||||
"expect": 200,
|
||||
"msg": "assert response status code"
|
||||
},
|
||||
{
|
||||
"check": "headers.\"Content-Type\"",
|
||||
"assert": "equals",
|
||||
"expect": "application/json; charset=utf-8",
|
||||
"msg": "assert response header Content-Type"
|
||||
},
|
||||
{
|
||||
"check": "body.url",
|
||||
"assert": "equals",
|
||||
"expect": "https://postman-echo.com/get?foo1=bar1&foo2=bar2",
|
||||
"msg": "assert response body url"
|
||||
}
|
||||
]
|
||||
}
|
||||
22
hrp/internal/scaffold/templates/api/get.yml
Normal file
22
hrp/internal/scaffold/templates/api/get.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
name: ""
|
||||
request:
|
||||
method: GET
|
||||
url: /get
|
||||
params:
|
||||
foo1: bar1
|
||||
foo2: bar2
|
||||
headers:
|
||||
Postman-Token: ea19464c-ddd4-4724-abe9-5e2b254c2723
|
||||
validate:
|
||||
- check: status_code
|
||||
assert: equals
|
||||
expect: 200
|
||||
msg: assert response status code
|
||||
- check: headers."Content-Type"
|
||||
assert: equals
|
||||
expect: application/json; charset=utf-8
|
||||
msg: assert response header Content-Type
|
||||
- check: body.url
|
||||
assert: equals
|
||||
expect: https://postman-echo.com/get?foo1=bar1&foo2=bar2
|
||||
msg: assert response body url
|
||||
45
hrp/internal/scaffold/templates/api/post.json
Normal file
45
hrp/internal/scaffold/templates/api/post.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"url": "/post",
|
||||
"headers": {
|
||||
"Content-Length": "58",
|
||||
"Content-Type": "text/plain",
|
||||
"Postman-Token": "$session_token"
|
||||
},
|
||||
"body": "This is expected to be sent back as part of response body."
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "status_code",
|
||||
"assert": "equals",
|
||||
"expect": 200,
|
||||
"msg": "assert response status code"
|
||||
},
|
||||
{
|
||||
"check": "headers.\"Content-Type\"",
|
||||
"assert": "equals",
|
||||
"expect": "application/json; charset=utf-8",
|
||||
"msg": "assert response header Content-Type"
|
||||
},
|
||||
{
|
||||
"check": "body.data",
|
||||
"assert": "equals",
|
||||
"expect": "This is expected to be sent back as part of response body.",
|
||||
"msg": "assert response body data"
|
||||
},
|
||||
{
|
||||
"check": "body.json",
|
||||
"assert": "equals",
|
||||
"expect": null,
|
||||
"msg": "assert response body json"
|
||||
},
|
||||
{
|
||||
"check": "body.url",
|
||||
"assert": "equals",
|
||||
"expect": "https://postman-echo.com/post",
|
||||
"msg": "assert response body url"
|
||||
}
|
||||
]
|
||||
}
|
||||
30
hrp/internal/scaffold/templates/api/post.yml
Normal file
30
hrp/internal/scaffold/templates/api/post.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
name: ""
|
||||
request:
|
||||
method: POST
|
||||
url: /post
|
||||
headers:
|
||||
Content-Length: "58"
|
||||
Content-Type: text/plain
|
||||
Postman-Token: $session_token
|
||||
body: This is expected to be sent back as part of response body.
|
||||
validate:
|
||||
- check: status_code
|
||||
assert: equals
|
||||
expect: 200
|
||||
msg: assert response status code
|
||||
- check: headers."Content-Type"
|
||||
assert: equals
|
||||
expect: application/json; charset=utf-8
|
||||
msg: assert response header Content-Type
|
||||
- check: body.data
|
||||
assert: equals
|
||||
expect: This is expected to be sent back as part of response body.
|
||||
msg: assert response body data
|
||||
- check: body.json
|
||||
assert: equals
|
||||
expect: null
|
||||
msg: assert response body json
|
||||
- check: body.url
|
||||
assert: equals
|
||||
expect: https://postman-echo.com/post
|
||||
msg: assert response body url
|
||||
45
hrp/internal/scaffold/templates/api/put.json
Normal file
45
hrp/internal/scaffold/templates/api/put.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"url": "/put",
|
||||
"headers": {
|
||||
"Content-Length": "58",
|
||||
"Content-Type": "text/plain",
|
||||
"Postman-Token": "5d357b2b-0f10-4ded-bc9a-299ebef7a2d5"
|
||||
},
|
||||
"body": "This is expected to be sent back as part of response body."
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "status_code",
|
||||
"assert": "equals",
|
||||
"expect": 200,
|
||||
"msg": "assert response status code"
|
||||
},
|
||||
{
|
||||
"check": "headers.\"Content-Type\"",
|
||||
"assert": "equals",
|
||||
"expect": "application/json; charset=utf-8",
|
||||
"msg": "assert response header Content-Type"
|
||||
},
|
||||
{
|
||||
"check": "body.data",
|
||||
"assert": "equals",
|
||||
"expect": "This is expected to be sent back as part of response body.",
|
||||
"msg": "assert response body data"
|
||||
},
|
||||
{
|
||||
"check": "body.json",
|
||||
"assert": "equals",
|
||||
"expect": null,
|
||||
"msg": "assert response body json"
|
||||
},
|
||||
{
|
||||
"check": "body.url",
|
||||
"assert": "equals",
|
||||
"expect": "https://postman-echo.com/put",
|
||||
"msg": "assert response body url"
|
||||
}
|
||||
]
|
||||
}
|
||||
30
hrp/internal/scaffold/templates/api/put.yml
Normal file
30
hrp/internal/scaffold/templates/api/put.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
name: ""
|
||||
request:
|
||||
method: PUT
|
||||
url: /put
|
||||
headers:
|
||||
Content-Length: "58"
|
||||
Content-Type: text/plain
|
||||
Postman-Token: 5d357b2b-0f10-4ded-bc9a-299ebef7a2d5
|
||||
body: This is expected to be sent back as part of response body.
|
||||
validate:
|
||||
- check: status_code
|
||||
assert: equals
|
||||
expect: 200
|
||||
msg: assert response status code
|
||||
- check: headers."Content-Type"
|
||||
assert: equals
|
||||
expect: application/json; charset=utf-8
|
||||
msg: assert response header Content-Type
|
||||
- check: body.data
|
||||
assert: equals
|
||||
expect: This is expected to be sent back as part of response body.
|
||||
msg: assert response body data
|
||||
- check: body.json
|
||||
assert: equals
|
||||
expect: null
|
||||
msg: assert response body json
|
||||
- check: body.url
|
||||
assert: equals
|
||||
expect: https://postman-echo.com/put
|
||||
msg: assert response body url
|
||||
78
hrp/internal/scaffold/templates/testcases/demo_ref_api.json
Normal file
78
hrp/internal/scaffold/templates/testcases/demo_ref_api.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"config": {
|
||||
"name": "api test demo",
|
||||
"variables": {
|
||||
"user_agent": "iOS/10.3",
|
||||
"device_sn": "TESTCASE_SETUP_XXX",
|
||||
"os_platform": "ios",
|
||||
"app_version": "2.8.6"
|
||||
},
|
||||
"base_url": "https://postman-echo.com",
|
||||
"herader": [
|
||||
{
|
||||
"Accept": "*/*",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"Cache-Control": "no-cache",
|
||||
"Connection": "keep-alive",
|
||||
"Host": "postman-echo.com",
|
||||
"User-Agent": "PostmanRuntime/7.28.4"
|
||||
}
|
||||
],
|
||||
"verify": false,
|
||||
"export": [
|
||||
"session_token"
|
||||
]
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "test api /get",
|
||||
"api": "api/get.json",
|
||||
"variables": {
|
||||
"user_agent": "iOS/10.4",
|
||||
"device_sn": "$device_sn",
|
||||
"os_platform": "ios",
|
||||
"app_version": "2.8.7"
|
||||
},
|
||||
"extract": {
|
||||
"session_token": "body.headers.\"postman-token\""
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "test api /post",
|
||||
"api": "api/post.json",
|
||||
"variables": {
|
||||
"user_agent": "iOS/10.5",
|
||||
"device_sn": "$device_sn",
|
||||
"os_platform": "ios",
|
||||
"app_version": "2.8.9"
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"eq": [
|
||||
"status_code",
|
||||
200
|
||||
]
|
||||
},
|
||||
{
|
||||
"eq": [
|
||||
"body.headers.postman-token",
|
||||
"ea19464c-ddd4-4724-abe9-5e2b254c2723"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "test api /put",
|
||||
"api": "api/put.json",
|
||||
"variables": {
|
||||
"user_agent": "iOS/10.6",
|
||||
"device_sn": "$device_sn",
|
||||
"os_platform": "ios",
|
||||
"app_version": "2.8.10"
|
||||
},
|
||||
"extract": {
|
||||
"session_token": "body.headers.\"postman-token\""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -193,6 +193,11 @@ type API struct {
|
||||
Extract map[string]string `json:"extract,omitempty" yaml:"extract,omitempty"`
|
||||
Validators []interface{} `json:"validate,omitempty" yaml:"validate,omitempty"`
|
||||
Export []string `json:"export,omitempty" yaml:"export,omitempty"`
|
||||
Path string
|
||||
}
|
||||
|
||||
func (api *API) GetPath() string {
|
||||
return api.Path
|
||||
}
|
||||
|
||||
func (api *API) ToAPI() (*API, error) {
|
||||
@@ -210,6 +215,7 @@ type Validator struct {
|
||||
// IAPI represents interface for api,
|
||||
// includes API and APIPath.
|
||||
type IAPI interface {
|
||||
GetPath() string
|
||||
ToAPI() (*API, error)
|
||||
}
|
||||
|
||||
@@ -219,8 +225,8 @@ type TStep struct {
|
||||
Name string `json:"name" yaml:"name"` // required
|
||||
Request *Request `json:"request,omitempty" yaml:"request,omitempty"`
|
||||
APIPath string `json:"api,omitempty" yaml:"api,omitempty"`
|
||||
TestCasePath string `json:"testcase,omitempty" yaml:"testcase,omitempty"`
|
||||
APIContent IAPI `json:"api_content,omitempty" yaml:"api_content,omitempty"`
|
||||
TestCasePath string `json:"testcase,omitempty" yaml:"testcase,omitempty"`
|
||||
TestCaseContent ITestCase `json:"testcase_content,omitempty" yaml:"testcase_content,omitempty"`
|
||||
Transaction *Transaction `json:"transaction,omitempty" yaml:"transaction,omitempty"`
|
||||
Rendezvous *Rendezvous `json:"rendezvous,omitempty" yaml:"rendezvous,omitempty"`
|
||||
@@ -287,6 +293,10 @@ type TCase struct {
|
||||
TestSteps []*TStep `json:"teststeps" yaml:"teststeps"`
|
||||
}
|
||||
|
||||
func (tc *TCase) Path() string {
|
||||
return tc.Config.Path
|
||||
}
|
||||
|
||||
// IStep represents interface for all types for teststeps, includes:
|
||||
// StepRequest, StepRequestWithOptionalArgs, StepRequestValidation, StepRequestExtraction,
|
||||
// StepTestCaseWithOptionalArgs,
|
||||
@@ -300,6 +310,7 @@ type IStep interface {
|
||||
// ITestCase represents interface for testcases,
|
||||
// includes TestCase and TestCasePath.
|
||||
type ITestCase interface {
|
||||
GetPath() string
|
||||
ToTestCase() (*TestCase, error)
|
||||
ToTCase() (*TCase, error)
|
||||
}
|
||||
@@ -311,6 +322,10 @@ type TestCase struct {
|
||||
TestSteps []IStep
|
||||
}
|
||||
|
||||
func (tc *TestCase) GetPath() string {
|
||||
return tc.Config.Path
|
||||
}
|
||||
|
||||
func (tc *TestCase) ToTestCase() (*TestCase, error) {
|
||||
return tc, nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package hrp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -742,7 +743,7 @@ func TestParseParameters(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
map[string]interface{}{
|
||||
"username-password": "${parameterize(../examples/hrp/account.csv)}",
|
||||
"username-password": fmt.Sprintf("${parameterize(%s/account.csv)}", hrpExamplesDir),
|
||||
"user_agent": []interface{}{"IOS/10.1", "IOS/10.2"}},
|
||||
6,
|
||||
},
|
||||
@@ -782,17 +783,17 @@ func TestParseParametersError(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
map[string]interface{}{
|
||||
"username_password": "${parameterize(../examples/hrp/account.csv)}",
|
||||
"username_password": fmt.Sprintf("${parameterize(%s/account.csv)}", hrpExamplesDir),
|
||||
"user_agent": []interface{}{"IOS/10.1", "IOS/10.2"}},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"username-password": "${parameterize(../examples/hrp/account.csv)}",
|
||||
"username-password": fmt.Sprintf("${parameterize(%s/account.csv)}", hrpExamplesDir),
|
||||
"user-agent": []interface{}{"IOS/10.1", "IOS/10.2"}},
|
||||
},
|
||||
{
|
||||
map[string]interface{}{
|
||||
"username-password": "${param(../examples/hrp/account.csv)}",
|
||||
"username-password": fmt.Sprintf("${param(%s/account.csv)}", hrpExamplesDir),
|
||||
"user_agent": []interface{}{"IOS/10.1", "IOS/10.2"}},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -40,14 +40,14 @@ func removeHashicorpPyPlugin() {
|
||||
os.Remove(templatesDir + "debugtalk.py")
|
||||
}
|
||||
|
||||
func TestHttpRunnerWithGoPlugin(t *testing.T) {
|
||||
func TestRunCaseWithGoPlugin(t *testing.T) {
|
||||
buildHashicorpGoPlugin()
|
||||
defer removeHashicorpGoPlugin()
|
||||
|
||||
assertRunTestCases(t)
|
||||
}
|
||||
|
||||
func TestHttpRunnerWithPythonPlugin(t *testing.T) {
|
||||
func TestRunCaseWithPythonPlugin(t *testing.T) {
|
||||
buildHashicorpPyPlugin()
|
||||
defer removeHashicorpPyPlugin()
|
||||
|
||||
@@ -59,19 +59,19 @@ func assertRunTestCases(t *testing.T) {
|
||||
Config: NewConfig("TestCase1").
|
||||
SetBaseURL("http://httpbin.org"),
|
||||
TestSteps: []IStep{
|
||||
NewStep("headers").
|
||||
NewStep("testcase1-step1").
|
||||
GET("/headers").
|
||||
Validate().
|
||||
AssertEqual("status_code", 200, "check status code").
|
||||
AssertEqual("headers.\"Content-Type\"", "application/json", "check http response Content-Type"),
|
||||
NewStep("user-agent").
|
||||
NewStep("testcase1-step2").
|
||||
GET("/user-agent").
|
||||
Validate().
|
||||
AssertEqual("status_code", 200, "check status code").
|
||||
AssertEqual("headers.\"Content-Type\"", "application/json", "check http response Content-Type"),
|
||||
NewStep("TestCase3").CallRefCase(
|
||||
NewStep("testcase1-step3").CallRefCase(
|
||||
&TestCase{
|
||||
Config: NewConfig("TestCase3").SetBaseURL("http://httpbin.org"),
|
||||
Config: NewConfig("testcase1-step3-ref-case").SetBaseURL("http://httpbin.org"),
|
||||
TestSteps: []IStep{
|
||||
NewStep("ip").
|
||||
GET("/ip").
|
||||
@@ -81,32 +81,23 @@ func assertRunTestCases(t *testing.T) {
|
||||
},
|
||||
},
|
||||
),
|
||||
NewStep("TestCase4").CallRefCase(&demoRefAPIYAMLPath),
|
||||
NewStep("TestCase5").CallRefCase(&demoTestCaseWithPluginJSONPath),
|
||||
NewStep("testcase1-step4").CallRefCase(&demoTestCaseWithPluginJSONPath),
|
||||
},
|
||||
}
|
||||
testcase2 := &TestCase{
|
||||
Config: NewConfig("TestCase2").SetWeight(3),
|
||||
}
|
||||
testcase3 := &TestCase{
|
||||
Config: NewConfig("TestCase1").
|
||||
SetBaseURL("https://postman-echo.com"),
|
||||
TestSteps: []IStep{
|
||||
NewStep("TestCase5").CallRefAPI(&demoAPIYAMLPath),
|
||||
},
|
||||
}
|
||||
testcase4 := &demoRefTestCaseJSONPath
|
||||
|
||||
r := NewRunner(t)
|
||||
r.SetPluginLogOn()
|
||||
err := r.Run(testcase1, testcase2, testcase3, testcase4)
|
||||
err := r.Run(testcase1, testcase2)
|
||||
if err != nil {
|
||||
t.Fatalf("run testcase error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitRendezvous(t *testing.T) {
|
||||
rendezvousBonudaryTestcase := &TestCase{
|
||||
func TestRunCaseWithRendezvous(t *testing.T) {
|
||||
rendezvousBoundaryTestcase := &TestCase{
|
||||
Config: NewConfig("run request with functions").
|
||||
SetBaseURL("https://postman-echo.com").
|
||||
WithVariables(map[string]interface{}{
|
||||
@@ -155,7 +146,7 @@ func TestInitRendezvous(t *testing.T) {
|
||||
{number: 100, percent: 1, timeout: 5000},
|
||||
}
|
||||
|
||||
rendezvousList := initRendezvous(rendezvousBonudaryTestcase, 100)
|
||||
rendezvousList := initRendezvous(rendezvousBoundaryTestcase, 100)
|
||||
|
||||
for i, r := range rendezvousList {
|
||||
if r.Number != expectedRendezvousParams[i].number {
|
||||
@@ -170,7 +161,7 @@ func TestInitRendezvous(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestThinkTime(t *testing.T) {
|
||||
func TestRunCaseWithThinkTime(t *testing.T) {
|
||||
buildHashicorpGoPlugin()
|
||||
defer removeHashicorpGoPlugin()
|
||||
|
||||
@@ -205,7 +196,8 @@ func TestThinkTime(t *testing.T) {
|
||||
{
|
||||
Config: NewConfig("TestCase5"),
|
||||
TestSteps: []IStep{
|
||||
NewStep("thinkTime").CallRefCase(&demoThinkTimeJsonPath), // think time: 3s, random pct: {"min_percentage":1, "max_percentage":1.5}, limit: 4s
|
||||
// think time: 3s, random pct: {"min_percentage":1, "max_percentage":1.5}, limit: 4s
|
||||
NewStep("thinkTime").CallRefCase(&demoTestCaseWithThinkTimePath),
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -247,3 +239,47 @@ func TestGenHTMLReport(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCaseWithPluginJSON(t *testing.T) {
|
||||
buildHashicorpGoPlugin()
|
||||
defer removeHashicorpGoPlugin()
|
||||
|
||||
err := NewRunner(nil).Run(&demoTestCaseWithPluginJSONPath) // hrp.Run(testCase)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCaseWithPluginYAML(t *testing.T) {
|
||||
buildHashicorpGoPlugin()
|
||||
defer removeHashicorpGoPlugin()
|
||||
|
||||
err := NewRunner(nil).Run(&demoTestCaseWithPluginYAMLPath) // hrp.Run(testCase)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCaseWithRefAPI(t *testing.T) {
|
||||
buildHashicorpGoPlugin()
|
||||
defer removeHashicorpGoPlugin()
|
||||
|
||||
err := NewRunner(nil).Run(&demoTestCaseWithRefAPIPath)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
testcase := &TestCase{
|
||||
Config: NewConfig("TestCase").
|
||||
SetBaseURL("https://postman-echo.com"),
|
||||
TestSteps: []IStep{
|
||||
NewStep("run referenced api").CallRefAPI(&demoAPIGETPath),
|
||||
},
|
||||
}
|
||||
|
||||
r := NewRunner(t)
|
||||
err = r.Run(testcase)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
21
hrp/step.go
21
hrp/step.go
@@ -1,6 +1,11 @@
|
||||
package hrp
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// NewConfig returns a new constructed testcase config with specified testcase name.
|
||||
func NewConfig(name string) *TConfig {
|
||||
@@ -163,7 +168,12 @@ func (s *StepRequest) PATCH(url string) *StepRequestWithOptionalArgs {
|
||||
|
||||
// CallRefCase calls a referenced testcase.
|
||||
func (s *StepRequest) CallRefCase(tc ITestCase) *StepTestCaseWithOptionalArgs {
|
||||
s.step.TestCaseContent, _ = tc.ToTestCase()
|
||||
var err error
|
||||
s.step.TestCaseContent, err = tc.ToTestCase()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to load testcase")
|
||||
os.Exit(1)
|
||||
}
|
||||
return &StepTestCaseWithOptionalArgs{
|
||||
step: s.step,
|
||||
}
|
||||
@@ -171,7 +181,12 @@ func (s *StepRequest) CallRefCase(tc ITestCase) *StepTestCaseWithOptionalArgs {
|
||||
|
||||
// CallRefAPI calls a referenced api.
|
||||
func (s *StepRequest) CallRefAPI(api IAPI) *StepAPIWithOptionalArgs {
|
||||
s.step.APIContent, _ = api.ToAPI()
|
||||
var err error
|
||||
s.step.APIContent, err = api.ToAPI()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("failed to load api")
|
||||
os.Exit(1)
|
||||
}
|
||||
return &StepAPIWithOptionalArgs{
|
||||
step: s.step,
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/httprunner/httprunner/hrp"
|
||||
)
|
||||
|
||||
// generated by examples/data/har/demo.har using HttpRunner v3.1.6
|
||||
var (
|
||||
demoHttpRunnerJSONPath hrp.TestCasePath = "../../examples/hrp/demo_httprunner.json"
|
||||
demoHttpRunnerYAMLPath hrp.TestCasePath = "../../examples/hrp/demo_httprunner.yaml"
|
||||
)
|
||||
|
||||
func TestCompatTestCase(t *testing.T) {
|
||||
err := hrp.NewRunner(t).Run(&demoHttpRunnerJSONPath)
|
||||
if err != nil {
|
||||
t.Fatalf("run testcase error: %v", err)
|
||||
}
|
||||
|
||||
err = hrp.NewRunner(t).Run(&demoHttpRunnerYAMLPath)
|
||||
if err != nil {
|
||||
t.Fatalf("run testcase error: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user