mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-08 00:47:36 +08:00
refactor: move tests
This commit is contained in:
@@ -10,11 +10,11 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/httprunner/funplugin/fungo"
|
|
||||||
"github.com/httprunner/funplugin/myexec"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/funplugin/fungo"
|
||||||
|
"github.com/httprunner/funplugin/myexec"
|
||||||
"github.com/httprunner/httprunner/v5/code"
|
"github.com/httprunner/httprunner/v5/code"
|
||||||
"github.com/httprunner/httprunner/v5/internal/builtin"
|
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||||
"github.com/httprunner/httprunner/v5/internal/config"
|
"github.com/httprunner/httprunner/v5/internal/config"
|
||||||
|
|||||||
-141
@@ -1,141 +0,0 @@
|
|||||||
package hrp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRun(t *testing.T) {
|
|
||||||
err := BuildPlugin(tmpl("plugin/debugtalk.go"), "./debugtalk.bin")
|
|
||||||
if !assert.Nil(t, err) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
|
|
||||||
genDebugTalkPyPath := filepath.Join(tmpl("plugin/"), PluginPySourceGenFile)
|
|
||||||
err = BuildPlugin(tmpl("plugin/debugtalk.py"), genDebugTalkPyPath)
|
|
||||||
if !assert.Nil(t, err) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
|
|
||||||
contentBytes, err := readFile(genDebugTalkPyPath)
|
|
||||||
if !assert.Nil(t, err) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
|
|
||||||
content := string(contentBytes)
|
|
||||||
if !assert.Contains(t, content, "import funppy") {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !assert.Contains(t, content, "funppy.register") {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
|
|
||||||
reg, _ := regexp.Compile(`funppy\.register`)
|
|
||||||
matchedSlice := reg.FindAllStringSubmatch(content, -1)
|
|
||||||
if !assert.Len(t, matchedSlice, 10) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindAllPythonFunctionNames(t *testing.T) {
|
|
||||||
content := `
|
|
||||||
def test_1(): # exported function
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _test_2(): # exported function
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __test_3(): # private function
|
|
||||||
pass
|
|
||||||
|
|
||||||
# def test_4(): # commented out function
|
|
||||||
# pass
|
|
||||||
|
|
||||||
def Test5(): # exported function
|
|
||||||
pass
|
|
||||||
`
|
|
||||||
names, err := regexPyFunctionName.findAllFunctionNames(content)
|
|
||||||
if !assert.Nil(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Contains(t, names, "test_1") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Contains(t, names, "Test5") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Contains(t, names, "_test_2") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.NotContains(t, names, "__test_3") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
// commented out function
|
|
||||||
if !assert.NotContains(t, names, "test_4") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindAllGoFunctionNames(t *testing.T) {
|
|
||||||
content := `
|
|
||||||
func Test1() { // exported function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func testFunc2() { // exported function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { // private function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func _Test3() { // exported function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// func Test4() { // commented out function
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
`
|
|
||||||
names, err := regexGoFunctionName.findAllFunctionNames(content)
|
|
||||||
if !assert.Nil(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Contains(t, names, "Test1") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Contains(t, names, "testFunc2") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.NotContains(t, names, "init") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
if !assert.Contains(t, names, "_Test3") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
// commented out function
|
|
||||||
if !assert.NotContains(t, names, "Test4") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFindAllGoFunctionNamesAbnormal(t *testing.T) {
|
|
||||||
content := `
|
|
||||||
func init() { // private function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() { // should not define main() function
|
|
||||||
return
|
|
||||||
}
|
|
||||||
`
|
|
||||||
_, err := regexGoFunctionName.findAllFunctionNames(content)
|
|
||||||
if !assert.NotNil(t, err) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -80,7 +80,7 @@ func (c *TConfig) WithParameters(parameters map[string]interface{}) *TConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetThinkTime sets think time config for current testcase.
|
// SetThinkTime sets think time config for current testcase.
|
||||||
func (c *TConfig) SetThinkTime(strategy thinkTimeStrategy, cfg interface{}, limit float64) *TConfig {
|
func (c *TConfig) SetThinkTime(strategy ThinkTimeStrategy, cfg interface{}, limit float64) *TConfig {
|
||||||
c.ThinkTimeSetting = &ThinkTimeConfig{strategy, cfg, limit}
|
c.ThinkTimeSetting = &ThinkTimeConfig{strategy, cfg, limit}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ func (c *TConfig) DisableAutoPopupHandler() *TConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ThinkTimeConfig struct {
|
type ThinkTimeConfig struct {
|
||||||
Strategy thinkTimeStrategy `json:"strategy,omitempty" yaml:"strategy,omitempty"` // default、random、multiply、ignore
|
Strategy ThinkTimeStrategy `json:"strategy,omitempty" yaml:"strategy,omitempty"` // default、random、multiply、ignore
|
||||||
Setting interface{} `json:"setting,omitempty" yaml:"setting,omitempty"` // random(map): {"min_percentage": 0.5, "max_percentage": 1.5}; 10、multiply(float64): 1.5
|
Setting interface{} `json:"setting,omitempty" yaml:"setting,omitempty"` // random(map): {"min_percentage": 0.5, "max_percentage": 1.5}; 10、multiply(float64): 1.5
|
||||||
Limit float64 `json:"limit,omitempty" yaml:"limit,omitempty"` // limit think time no more than specific time, ignore if value <= 0
|
Limit float64 `json:"limit,omitempty" yaml:"limit,omitempty"` // limit think time no more than specific time, ignore if value <= 0
|
||||||
}
|
}
|
||||||
@@ -205,10 +205,10 @@ func (ttc *ThinkTimeConfig) checkThinkTime() {
|
|||||||
}
|
}
|
||||||
// unset strategy, set default strategy
|
// unset strategy, set default strategy
|
||||||
if ttc.Strategy == "" {
|
if ttc.Strategy == "" {
|
||||||
ttc.Strategy = thinkTimeDefault
|
ttc.Strategy = ThinkTimeDefault
|
||||||
}
|
}
|
||||||
// check think time
|
// check think time
|
||||||
if ttc.Strategy == thinkTimeRandomPercentage {
|
if ttc.Strategy == ThinkTimeRandomPercentage {
|
||||||
if ttc.Setting == nil || reflect.TypeOf(ttc.Setting).Kind() != reflect.Map {
|
if ttc.Setting == nil || reflect.TypeOf(ttc.Setting).Kind() != reflect.Map {
|
||||||
ttc.Setting = thinkTimeDefaultRandom
|
ttc.Setting = thinkTimeDefaultRandom
|
||||||
return
|
return
|
||||||
@@ -237,7 +237,7 @@ func (ttc *ThinkTimeConfig) checkThinkTime() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ttc.Setting = map[string]float64{"min_percentage": left, "max_percentage": right}
|
ttc.Setting = map[string]float64{"min_percentage": left, "max_percentage": right}
|
||||||
} else if ttc.Strategy == thinkTimeMultiply {
|
} else if ttc.Strategy == ThinkTimeMultiply {
|
||||||
if ttc.Setting == nil {
|
if ttc.Setting == nil {
|
||||||
ttc.Setting = float64(0) // default
|
ttc.Setting = float64(0) // default
|
||||||
return
|
return
|
||||||
@@ -248,19 +248,19 @@ func (ttc *ThinkTimeConfig) checkThinkTime() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
ttc.Setting = value
|
ttc.Setting = value
|
||||||
} else if ttc.Strategy != thinkTimeIgnore {
|
} else if ttc.Strategy != ThinkTimeIgnore {
|
||||||
// unrecognized strategy, set default strategy
|
// unrecognized strategy, set default strategy
|
||||||
ttc.Strategy = thinkTimeDefault
|
ttc.Strategy = ThinkTimeDefault
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type thinkTimeStrategy string
|
type ThinkTimeStrategy string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
thinkTimeDefault thinkTimeStrategy = "default" // as recorded
|
ThinkTimeDefault ThinkTimeStrategy = "default" // as recorded
|
||||||
thinkTimeRandomPercentage thinkTimeStrategy = "random_percentage" // use random percentage of recorded think time
|
ThinkTimeRandomPercentage ThinkTimeStrategy = "random_percentage" // use random percentage of recorded think time
|
||||||
thinkTimeMultiply thinkTimeStrategy = "multiply" // multiply recorded think time
|
ThinkTimeMultiply ThinkTimeStrategy = "multiply" // multiply recorded think time
|
||||||
thinkTimeIgnore thinkTimeStrategy = "ignore" // ignore recorded think time
|
ThinkTimeIgnore ThinkTimeStrategy = "ignore" // ignore recorded think time
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
@@ -225,6 +225,22 @@ func InterfaceType(raw interface{}) string {
|
|||||||
return reflect.TypeOf(raw).String()
|
return reflect.TypeOf(raw).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoadFile(path string) ([]byte, error) {
|
||||||
|
var err error
|
||||||
|
path, err = filepath.Abs(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Str("path", path).Msg("convert absolute path failed")
|
||||||
|
return nil, errors.Wrap(code.LoadFileError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("read file failed")
|
||||||
|
return nil, errors.Wrap(code.LoadFileError, err.Error())
|
||||||
|
}
|
||||||
|
return file, 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 := os.ReadFile(path)
|
file, err := os.ReadFile(path)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v5.0.0+2503051104
|
v5.0.0+2503051147
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v5/code"
|
"github.com/httprunner/httprunner/v5/code"
|
||||||
|
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||||
"github.com/httprunner/httprunner/v5/internal/json"
|
"github.com/httprunner/httprunner/v5/internal/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ func LoadTestCases(tests ...ITestCase) ([]*TestCase, error) {
|
|||||||
// LoadFileObject loads file content with file extension and assigns to structObj
|
// LoadFileObject loads file content with file extension and assigns to structObj
|
||||||
func LoadFileObject(path string, structObj interface{}) (err error) {
|
func LoadFileObject(path string, structObj interface{}) (err error) {
|
||||||
log.Info().Str("path", path).Msg("load file")
|
log.Info().Str("path", path).Msg("load file")
|
||||||
file, err := readFile(path)
|
file, err := builtin.LoadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "read file failed")
|
return errors.Wrap(err, "read file failed")
|
||||||
}
|
}
|
||||||
@@ -145,19 +146,3 @@ func parseEnvContent(file []byte, obj interface{}) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readFile(path string) ([]byte, error) {
|
|
||||||
var err error
|
|
||||||
path, err = filepath.Abs(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Str("path", path).Msg("convert absolute path failed")
|
|
||||||
return nil, errors.Wrap(code.LoadFileError, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("read file failed")
|
|
||||||
return nil, errors.Wrap(code.LoadFileError, err.Error())
|
|
||||||
}
|
|
||||||
return file, nil
|
|
||||||
}
|
|
||||||
|
|||||||
+29
-29
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
type TParamsConfig struct {
|
type TParamsConfig struct {
|
||||||
PickOrder iteratorPickOrder `json:"pick_order,omitempty" yaml:"pick_order,omitempty"` // overall pick-order strategy
|
PickOrder iteratorPickOrder `json:"pick_order,omitempty" yaml:"pick_order,omitempty"` // overall pick-order strategy
|
||||||
Strategies map[string]iteratorStrategy `json:"strategies,omitempty" yaml:"strategies,omitempty"` // individual strategies for each parameters
|
Strategies map[string]IteratorStrategy `json:"strategies,omitempty" yaml:"strategies,omitempty"` // individual strategies for each parameters
|
||||||
Limit int `json:"limit,omitempty" yaml:"limit,omitempty"`
|
Limit int `json:"limit,omitempty" yaml:"limit,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,13 +35,13 @@ const (
|
|||||||
*/
|
*/
|
||||||
type Parameters []map[string]interface{}
|
type Parameters []map[string]interface{}
|
||||||
|
|
||||||
type iteratorStrategy struct {
|
type IteratorStrategy struct {
|
||||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||||
PickOrder iteratorPickOrder `json:"pick_order,omitempty" yaml:"pick_order,omitempty"`
|
PickOrder iteratorPickOrder `json:"pick_order,omitempty" yaml:"pick_order,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) initParametersIterator(cfg *TConfig) (*ParametersIterator, error) {
|
func (p *Parser) InitParametersIterator(cfg *TConfig) (*ParametersIterator, error) {
|
||||||
parameters, err := p.loadParameters(cfg.Parameters, cfg.Variables)
|
parameters, err := p.LoadParameters(cfg.Parameters, cfg.Variables)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -57,13 +57,13 @@ func newParametersIterator(parameters map[string]Parameters, config *TParamsConf
|
|||||||
hasNext: true,
|
hasNext: true,
|
||||||
sequentialParameters: nil,
|
sequentialParameters: nil,
|
||||||
randomParameterNames: nil,
|
randomParameterNames: nil,
|
||||||
limit: config.Limit,
|
Limit: config.Limit,
|
||||||
index: 0,
|
Index: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(parameters) == 0 {
|
if len(parameters) == 0 {
|
||||||
iterator.data = map[string]Parameters{}
|
iterator.data = map[string]Parameters{}
|
||||||
iterator.limit = 1
|
iterator.Limit = 1
|
||||||
return iterator
|
return iterator
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,24 +85,24 @@ func newParametersIterator(parameters map[string]Parameters, config *TParamsConf
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate cartesian product for sequential parameters
|
// generate cartesian product for sequential parameters
|
||||||
iterator.sequentialParameters = genCartesianProduct(parametersList)
|
iterator.sequentialParameters = GenCartesianProduct(parametersList)
|
||||||
|
|
||||||
if iterator.limit < 0 {
|
if iterator.Limit < 0 {
|
||||||
log.Warn().Msg("parameters unlimited mode is only supported for load testing")
|
log.Warn().Msg("parameters unlimited mode is only supported for load testing")
|
||||||
iterator.limit = 0
|
iterator.Limit = 0
|
||||||
}
|
}
|
||||||
if iterator.limit == 0 {
|
if iterator.Limit == 0 {
|
||||||
// limit not set
|
// limit not set
|
||||||
if len(iterator.sequentialParameters) > 0 {
|
if len(iterator.sequentialParameters) > 0 {
|
||||||
// use cartesian product of sequential parameters size as limit
|
// use cartesian product of sequential parameters size as limit
|
||||||
iterator.limit = len(iterator.sequentialParameters)
|
iterator.Limit = len(iterator.sequentialParameters)
|
||||||
} else {
|
} else {
|
||||||
// all parameters are selected by random
|
// all parameters are selected by random
|
||||||
// only run once
|
// only run once
|
||||||
iterator.limit = 1
|
iterator.Limit = 1
|
||||||
}
|
}
|
||||||
} else { // limit > 0
|
} else { // limit > 0
|
||||||
log.Info().Int("limit", iterator.limit).Msg("set limit for parameters")
|
log.Info().Int("limit", iterator.Limit).Msg("set limit for parameters")
|
||||||
}
|
}
|
||||||
|
|
||||||
return iterator
|
return iterator
|
||||||
@@ -114,14 +114,14 @@ type ParametersIterator struct {
|
|||||||
hasNext bool // cache query result
|
hasNext bool // cache query result
|
||||||
sequentialParameters Parameters // cartesian product for sequential parameters
|
sequentialParameters Parameters // cartesian product for sequential parameters
|
||||||
randomParameterNames []string // value is parameter names
|
randomParameterNames []string // value is parameter names
|
||||||
limit int // limit count for iteration
|
Limit int // limit count for iteration
|
||||||
index int // current iteration index
|
Index int // current iteration index
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUnlimitedMode is used for load testing
|
// SetUnlimitedMode is used for load testing
|
||||||
func (iter *ParametersIterator) SetUnlimitedMode() {
|
func (iter *ParametersIterator) SetUnlimitedMode() {
|
||||||
log.Info().Msg("set parameters unlimited mode")
|
log.Info().Msg("set parameters unlimited mode")
|
||||||
iter.limit = -1
|
iter.Limit = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter *ParametersIterator) HasNext() bool {
|
func (iter *ParametersIterator) HasNext() bool {
|
||||||
@@ -130,12 +130,12 @@ func (iter *ParametersIterator) HasNext() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// unlimited mode
|
// unlimited mode
|
||||||
if iter.limit == -1 {
|
if iter.Limit == -1 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// reached limit
|
// reached limit
|
||||||
if iter.index >= iter.limit {
|
if iter.Index >= iter.Limit {
|
||||||
// cache query result
|
// cache query result
|
||||||
iter.hasNext = false
|
iter.hasNext = false
|
||||||
return false
|
return false
|
||||||
@@ -155,11 +155,11 @@ func (iter *ParametersIterator) Next() map[string]interface{} {
|
|||||||
var selectedParameters map[string]interface{}
|
var selectedParameters map[string]interface{}
|
||||||
if len(iter.sequentialParameters) == 0 {
|
if len(iter.sequentialParameters) == 0 {
|
||||||
selectedParameters = make(map[string]interface{})
|
selectedParameters = make(map[string]interface{})
|
||||||
} else if iter.index < len(iter.sequentialParameters) {
|
} else if iter.Index < len(iter.sequentialParameters) {
|
||||||
selectedParameters = iter.sequentialParameters[iter.index]
|
selectedParameters = iter.sequentialParameters[iter.Index]
|
||||||
} else {
|
} else {
|
||||||
// loop back to the first sequential parameter
|
// loop back to the first sequential parameter
|
||||||
index := iter.index % len(iter.sequentialParameters)
|
index := iter.Index % len(iter.sequentialParameters)
|
||||||
selectedParameters = iter.sequentialParameters[index]
|
selectedParameters = iter.sequentialParameters[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,8 +172,8 @@ func (iter *ParametersIterator) Next() map[string]interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iter.index++
|
iter.Index++
|
||||||
if iter.limit > 0 && iter.index >= iter.limit {
|
if iter.Limit > 0 && iter.Index >= iter.Limit {
|
||||||
iter.hasNext = false
|
iter.hasNext = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ func (iter *ParametersIterator) Data() map[string]interface{} {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func genCartesianProduct(multiParameters []Parameters) Parameters {
|
func GenCartesianProduct(multiParameters []Parameters) Parameters {
|
||||||
if len(multiParameters) == 0 {
|
if len(multiParameters) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -208,7 +208,7 @@ func genCartesianProduct(multiParameters []Parameters) Parameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
loadParameters loads parameters from multiple sources.
|
LoadParameters loads parameters from multiple sources.
|
||||||
|
|
||||||
parameter value may be in three types:
|
parameter value may be in three types:
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ parameter value may be in three types:
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
func (p *Parser) loadParameters(configParameters map[string]interface{}, variablesMapping map[string]interface{}) (
|
func (p *Parser) LoadParameters(configParameters map[string]interface{}, variablesMapping map[string]interface{}) (
|
||||||
map[string]Parameters, error) {
|
map[string]Parameters, error) {
|
||||||
|
|
||||||
if len(configParameters) == 0 {
|
if len(configParameters) == 0 {
|
||||||
@@ -291,7 +291,7 @@ func (p *Parser) loadParameters(configParameters map[string]interface{}, variabl
|
|||||||
return nil, errors.New("config parameters raw value format error")
|
return nil, errors.New("config parameters raw value format error")
|
||||||
}
|
}
|
||||||
|
|
||||||
parameterSlice, err := convertParameters(k, parametersRawList)
|
parameterSlice, err := ConvertParameters(k, parametersRawList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ case 3:
|
|||||||
key = "username-password"
|
key = "username-password"
|
||||||
parametersRawList = [["test1", "111111"], ["test2", "222222"]]
|
parametersRawList = [["test1", "111111"], ["test2", "222222"]]
|
||||||
*/
|
*/
|
||||||
func convertParameters(key string, parametersRawList interface{}) (parameterSlice []map[string]interface{}, err error) {
|
func ConvertParameters(key string, parametersRawList interface{}) (parameterSlice []map[string]interface{}, err error) {
|
||||||
parametersRawSlice := reflect.ValueOf(parametersRawList)
|
parametersRawSlice := reflect.ValueOf(parametersRawList)
|
||||||
if parametersRawSlice.Kind() != reflect.Slice {
|
if parametersRawSlice.Kind() != reflect.Slice {
|
||||||
return nil, errors.New("parameters raw value is not list")
|
return nil, errors.New("parameters raw value is not list")
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/httprunner/funplugin"
|
|
||||||
"github.com/httprunner/funplugin/fungo"
|
|
||||||
"github.com/maja42/goval"
|
"github.com/maja42/goval"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/funplugin"
|
||||||
|
"github.com/httprunner/funplugin/fungo"
|
||||||
"github.com/httprunner/httprunner/v5/code"
|
"github.com/httprunner/httprunner/v5/code"
|
||||||
"github.com/httprunner/httprunner/v5/internal/builtin"
|
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newParser() *Parser {
|
func NewParser() *Parser {
|
||||||
return &Parser{}
|
return &Parser{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+202
-9
@@ -1,8 +1,11 @@
|
|||||||
package hrp
|
package hrp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -208,7 +211,7 @@ func TestParseDataStringWithVariables(t *testing.T) {
|
|||||||
{"abc$var_5", "abctrue"}, // "abcTrue"
|
{"abc$var_5", "abctrue"}, // "abcTrue"
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -233,7 +236,7 @@ func TestParseDataStringWithUndefinedVariables(t *testing.T) {
|
|||||||
{"/api/$SECRET_KEY", "/api/$SECRET_KEY"}, // raise error
|
{"/api/$SECRET_KEY", "/api/$SECRET_KEY"}, // raise error
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
@@ -278,7 +281,7 @@ func TestParseDataStringWithVariablesAbnormal(t *testing.T) {
|
|||||||
{"ABC$var_1{}a", "ABCabc{}a"}, // {}
|
{"ABC$var_1{}a", "ABCabc{}a"}, // {}
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -309,7 +312,7 @@ func TestParseDataMapWithVariables(t *testing.T) {
|
|||||||
{map[string]interface{}{"$var2": "$val1"}, map[string]interface{}{"123": 200}},
|
{map[string]interface{}{"$var2": "$val1"}, map[string]interface{}{"123": 200}},
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
parsedData, err := parser.Parse(data.expr, variablesMapping)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -343,7 +346,7 @@ func TestParseHeaders(t *testing.T) {
|
|||||||
{map[string]string{"$var2": "$val2"}, map[string]string{"123": "<nil>"}},
|
{map[string]string{"$var2": "$val2"}, map[string]string{"123": "<nil>"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
parsedHeaders, err := parser.ParseHeaders(data.rawHeaders, variablesMapping)
|
parsedHeaders, err := parser.ParseHeaders(data.rawHeaders, variablesMapping)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -488,7 +491,7 @@ func TestMergeValidators(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCallBuiltinFunction(t *testing.T) {
|
func TestCallBuiltinFunction(t *testing.T) {
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
|
|
||||||
// call function without arguments
|
// call function without arguments
|
||||||
_, err := parser.callFunc("get_timestamp")
|
_, err := parser.callFunc("get_timestamp")
|
||||||
@@ -601,7 +604,7 @@ func TestParseDataStringWithFunctions(t *testing.T) {
|
|||||||
{"123${gen_random_string($n)}abc", 11},
|
{"123${gen_random_string($n)}abc", 11},
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData1 {
|
for _, data := range testData1 {
|
||||||
value, err := parser.Parse(data.expr, variablesMapping)
|
value, err := parser.Parse(data.expr, variablesMapping)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -670,7 +673,7 @@ func TestParseVariables(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
value, err := parser.ParseVariables(data.rawVars)
|
value, err := parser.ParseVariables(data.rawVars)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
@@ -701,7 +704,7 @@ func TestParseVariablesAbnormal(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
parser := newParser()
|
parser := NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
value, err := parser.ParseVariables(data.rawVars)
|
value, err := parser.ParseVariables(data.rawVars)
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
@@ -784,3 +787,193 @@ func TestFindallVariables(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSearchJmespath(t *testing.T) {
|
||||||
|
testText := `{"a": {"b": "foo"}, "c": "bar", "d": {"e": [{"f": "foo"}, {"f": "bar"}]}}`
|
||||||
|
testData := []struct {
|
||||||
|
raw string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"body.a.b", "foo"},
|
||||||
|
{"body.c", "bar"},
|
||||||
|
{"body.d.e[0].f", "foo"},
|
||||||
|
{"body.d.e[1].f", "bar"},
|
||||||
|
}
|
||||||
|
resp := http.Response{}
|
||||||
|
resp.Body = io.NopCloser(strings.NewReader(testText))
|
||||||
|
respObj, err := newHttpResponseObject(t, NewParser(), &resp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
for _, data := range testData {
|
||||||
|
if !assert.Equal(t, data.expected, respObj.searchJmespath(data.raw)) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSearchRegexp(t *testing.T) {
|
||||||
|
testText := `
|
||||||
|
<ul class="nav navbar-nav navbar-right">
|
||||||
|
<li><a href="/order/addToCart" style="color: white"><i class="fa fa-shopping-cart fa-2x"></i><span class="badge">0</span></a></li>
|
||||||
|
<li class="dropdown">
|
||||||
|
<a class="dropdown-toggle" data-toggle="dropdown" href="#" style="color: white">
|
||||||
|
Leo <i class="fa fa-cog fa-2x"></i><span class="caret"></span></a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="/user/changePassword">Change Password</a></li>
|
||||||
|
<li><a href="/user/addAddress">Shipping</a></li>
|
||||||
|
<li><a href="/user/addCard">Payment</a></li>
|
||||||
|
<li><a href="/order/orderHistory">Order History</a></li>
|
||||||
|
<li><a href="/user/signOut">Sign Out</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li> </li>
|
||||||
|
<li><a href="/user/signOut" style="color: white"><i class="fa fa-sign-out fa-2x"></i>
|
||||||
|
Sign Out</a></li>
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
testData := []struct {
|
||||||
|
raw string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"/user/signOut\">(.*)</a></li>", "Sign Out"},
|
||||||
|
{"<li><a href=\"/user/(.*)\" style", "signOut"},
|
||||||
|
{" (.*) <i class=\"fa fa-cog fa-2x\"></i>", "Leo"},
|
||||||
|
}
|
||||||
|
// new response object
|
||||||
|
resp := http.Response{}
|
||||||
|
resp.Body = io.NopCloser(strings.NewReader(testText))
|
||||||
|
respObj, err := newHttpResponseObject(t, NewParser(), &resp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
for _, data := range testData {
|
||||||
|
if !assert.Equal(t, data.expected, respObj.searchRegexp(data.raw)) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConvertCheckExpr(t *testing.T) {
|
||||||
|
exprs := []struct {
|
||||||
|
before string
|
||||||
|
after string
|
||||||
|
}{
|
||||||
|
// normal check expression
|
||||||
|
{"a.b.c", "a.b.c"},
|
||||||
|
{"a.\"b-c\".d", "a.\"b-c\".d"},
|
||||||
|
{"a.b-c.d", "a.b-c.d"},
|
||||||
|
{"body.args.a[-1]", "body.args.a[-1]"},
|
||||||
|
// check expression using regex
|
||||||
|
{"covering (.*) testing,", "covering (.*) testing,"},
|
||||||
|
{" (.*) a-b-c", " (.*) a-b-c"},
|
||||||
|
// abnormal check expression
|
||||||
|
{"headers.Content-Type", "headers.\"Content-Type\""},
|
||||||
|
{"headers.\"Content-Type", "headers.\"Content-Type\""},
|
||||||
|
{"headers.Content-Type\"", "headers.\"Content-Type\""},
|
||||||
|
{"headers.User-Agent", "headers.\"User-Agent\""},
|
||||||
|
}
|
||||||
|
for _, expr := range exprs {
|
||||||
|
assert.Equal(t, expr.after, convertJmespathExpr(expr.before))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAllPythonFunctionNames(t *testing.T) {
|
||||||
|
content := `
|
||||||
|
def test_1(): # exported function
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _test_2(): # exported function
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __test_3(): # private function
|
||||||
|
pass
|
||||||
|
|
||||||
|
# def test_4(): # commented out function
|
||||||
|
# pass
|
||||||
|
|
||||||
|
def Test5(): # exported function
|
||||||
|
pass
|
||||||
|
`
|
||||||
|
names, err := regexPyFunctionName.findAllFunctionNames(content)
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Contains(t, names, "test_1") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Contains(t, names, "Test5") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Contains(t, names, "_test_2") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.NotContains(t, names, "__test_3") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
// commented out function
|
||||||
|
if !assert.NotContains(t, names, "test_4") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAllGoFunctionNames(t *testing.T) {
|
||||||
|
content := `
|
||||||
|
func Test1() { // exported function
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func testFunc2() { // exported function
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { // private function
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Test3() { // exported function
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// func Test4() { // commented out function
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
`
|
||||||
|
names, err := regexGoFunctionName.findAllFunctionNames(content)
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Contains(t, names, "Test1") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Contains(t, names, "testFunc2") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.NotContains(t, names, "init") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if !assert.Contains(t, names, "_Test3") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
// commented out function
|
||||||
|
if !assert.NotContains(t, names, "Test4") {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindAllGoFunctionNamesAbnormal(t *testing.T) {
|
||||||
|
content := `
|
||||||
|
func init() { // private function
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() { // should not define main() function
|
||||||
|
return
|
||||||
|
}
|
||||||
|
`
|
||||||
|
_, err := regexGoFunctionName.findAllFunctionNames(content)
|
||||||
|
if !assert.NotNil(t, err) {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/httprunner/funplugin"
|
|
||||||
"github.com/httprunner/funplugin/myexec"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/funplugin"
|
||||||
|
"github.com/httprunner/funplugin/myexec"
|
||||||
"github.com/httprunner/httprunner/v5/code"
|
"github.com/httprunner/httprunner/v5/code"
|
||||||
"github.com/httprunner/httprunner/v5/internal/config"
|
"github.com/httprunner/httprunner/v5/internal/config"
|
||||||
"github.com/httprunner/httprunner/v5/internal/sdk"
|
"github.com/httprunner/httprunner/v5/internal/sdk"
|
||||||
@@ -39,7 +39,7 @@ func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err er
|
|||||||
if path == "" {
|
if path == "" {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
pluginPath, err := locatePlugin(path)
|
pluginPath, err := LocatePlugin(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Str("path", path).Msg("locate plugin failed")
|
log.Warn().Str("path", path).Msg("locate plugin failed")
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -100,21 +100,21 @@ func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func locatePlugin(path string) (pluginPath string, err error) {
|
func LocatePlugin(path string) (pluginPath string, err error) {
|
||||||
log.Info().Str("path", path).Msg("locate plugin")
|
log.Info().Str("path", path).Msg("locate plugin")
|
||||||
// priority: hashicorp plugin (debugtalk.bin > debugtalk.py) > go plugin (debugtalk.so)
|
// priority: hashicorp plugin (debugtalk.bin > debugtalk.py) > go plugin (debugtalk.so)
|
||||||
|
|
||||||
pluginPath, err = locateFile(path, PluginHashicorpGoBuiltFile)
|
pluginPath, err = LocateFile(path, PluginHashicorpGoBuiltFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginPath, err = locateFile(path, PluginPySourceFile)
|
pluginPath, err = LocateFile(path, PluginPySourceFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginPath, err = locateFile(path, PluginGoBuiltFile)
|
pluginPath, err = LocateFile(path, PluginGoBuiltFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -122,9 +122,9 @@ func locatePlugin(path string) (pluginPath string, err error) {
|
|||||||
return "", errors.New("plugin file not found")
|
return "", errors.New("plugin file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// locateFile searches destFile upward recursively until system root dir
|
// LocateFile searches destFile upward recursively until system root dir
|
||||||
// if not found, then searches in hrp executable dir
|
// if not found, then searches in hrp executable dir
|
||||||
func locateFile(startPath string, destFile string) (pluginPath string, err error) {
|
func LocateFile(startPath string, destFile string) (pluginPath string, err error) {
|
||||||
stat, err := os.Stat(startPath)
|
stat, err := os.Stat(startPath)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return "", errors.Wrap(err, "start path not exists")
|
return "", errors.Wrap(err, "start path not exists")
|
||||||
@@ -153,7 +153,7 @@ func locateFile(startPath string, destFile string) (pluginPath string, err error
|
|||||||
return "", errors.New("searched to system root dir, plugin file not found")
|
return "", errors.New("searched to system root dir, plugin file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return locateFile(parentDir, destFile)
|
return LocateFile(parentDir, destFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// locateExecutable finds destFile in hrp executable dir
|
// locateExecutable finds destFile in hrp executable dir
|
||||||
@@ -173,13 +173,13 @@ func locateExecutable(destFile string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetProjectRootDirPath(path string) (rootDir string, err error) {
|
func GetProjectRootDirPath(path string) (rootDir string, err error) {
|
||||||
pluginPath, err := locatePlugin(path)
|
pluginPath, err := LocatePlugin(path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rootDir = filepath.Dir(pluginPath)
|
rootDir = filepath.Dir(pluginPath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// fix: no debugtalk file in project but having proj.json created by startproject
|
// fix: no debugtalk file in project but having proj.json created by startproject
|
||||||
projPath, err := locateFile(path, projectInfoFile)
|
projPath, err := LocateFile(path, projectInfoFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rootDir = filepath.Dir(projPath)
|
rootDir = filepath.Dir(projPath)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -17,13 +17,14 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/httprunner/funplugin"
|
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
|
||||||
|
"github.com/httprunner/funplugin"
|
||||||
"github.com/httprunner/httprunner/v5/code"
|
"github.com/httprunner/httprunner/v5/code"
|
||||||
|
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||||
"github.com/httprunner/httprunner/v5/internal/sdk"
|
"github.com/httprunner/httprunner/v5/internal/sdk"
|
||||||
"github.com/httprunner/httprunner/v5/internal/version"
|
"github.com/httprunner/httprunner/v5/internal/version"
|
||||||
"github.com/httprunner/httprunner/v5/uixt"
|
"github.com/httprunner/httprunner/v5/uixt"
|
||||||
@@ -281,7 +282,7 @@ func (r *HRPRunner) NewCaseRunner(testcase TestCase) (*CaseRunner, error) {
|
|||||||
caseRunner := &CaseRunner{
|
caseRunner := &CaseRunner{
|
||||||
TestCase: testcase,
|
TestCase: testcase,
|
||||||
hrpRunner: r,
|
hrpRunner: r,
|
||||||
parser: newParser(),
|
parser: NewParser(),
|
||||||
uixtDrivers: make(map[string]*uixt.XTDriver),
|
uixtDrivers: make(map[string]*uixt.XTDriver),
|
||||||
}
|
}
|
||||||
config := testcase.Config.Get()
|
config := testcase.Config.Get()
|
||||||
@@ -296,7 +297,7 @@ func (r *HRPRunner) NewCaseRunner(testcase TestCase) (*CaseRunner, error) {
|
|||||||
|
|
||||||
// load plugin info to testcase config
|
// load plugin info to testcase config
|
||||||
pluginPath := plugin.Path()
|
pluginPath := plugin.Path()
|
||||||
pluginContent, err := readFile(pluginPath)
|
pluginContent, err := builtin.LoadFile(pluginPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -407,7 +408,7 @@ func (r *CaseRunner) parseConfig() (parsedConfig *TConfig, err error) {
|
|||||||
parsedConfig.WebSocketSetting.checkWebSocket()
|
parsedConfig.WebSocketSetting.checkWebSocket()
|
||||||
|
|
||||||
// parse testcase config parameters
|
// parse testcase config parameters
|
||||||
parametersIterator, err := r.parser.initParametersIterator(parsedConfig)
|
parametersIterator, err := r.parser.InitParametersIterator(parsedConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).
|
log.Error().Err(err).
|
||||||
Interface("parameters", parsedConfig.Parameters).
|
Interface("parameters", parsedConfig.Parameters).
|
||||||
|
|||||||
+2
-1
@@ -5,9 +5,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v5/uixt"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v5/uixt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StepFunction implements IStep interface.
|
// StepFunction implements IStep interface.
|
||||||
|
|||||||
+21
-21
@@ -30,13 +30,13 @@ import (
|
|||||||
type HTTPMethod string
|
type HTTPMethod string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
httpGET HTTPMethod = "GET"
|
HTTP_GET HTTPMethod = "GET"
|
||||||
httpHEAD HTTPMethod = "HEAD"
|
HTTP_HEAD HTTPMethod = "HEAD"
|
||||||
httpPOST HTTPMethod = "POST"
|
HTTP_POST HTTPMethod = "POST"
|
||||||
httpPUT HTTPMethod = "PUT"
|
HTTP_PUT HTTPMethod = "PUT"
|
||||||
httpDELETE HTTPMethod = "DELETE"
|
HTTP_DELETE HTTPMethod = "DELETE"
|
||||||
httpOPTIONS HTTPMethod = "OPTIONS"
|
HTTP_OPTIONS HTTPMethod = "OPTIONS"
|
||||||
httpPATCH HTTPMethod = "PATCH"
|
HTTP_PATCH HTTPMethod = "PATCH"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request represents HTTP request data structure.
|
// Request represents HTTP request data structure.
|
||||||
@@ -566,11 +566,11 @@ func (s *StepRequest) Loop(times int) *StepRequest {
|
|||||||
// GET makes a HTTP GET request.
|
// GET makes a HTTP GET request.
|
||||||
func (s *StepRequest) GET(url string) *StepRequestWithOptionalArgs {
|
func (s *StepRequest) GET(url string) *StepRequestWithOptionalArgs {
|
||||||
if s.Request != nil {
|
if s.Request != nil {
|
||||||
s.Request.Method = httpGET
|
s.Request.Method = HTTP_GET
|
||||||
s.Request.URL = url
|
s.Request.URL = url
|
||||||
} else {
|
} else {
|
||||||
s.Request = &Request{
|
s.Request = &Request{
|
||||||
Method: httpGET,
|
Method: HTTP_GET,
|
||||||
URL: url,
|
URL: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,11 +582,11 @@ func (s *StepRequest) GET(url string) *StepRequestWithOptionalArgs {
|
|||||||
// HEAD makes a HTTP HEAD request.
|
// HEAD makes a HTTP HEAD request.
|
||||||
func (s *StepRequest) HEAD(url string) *StepRequestWithOptionalArgs {
|
func (s *StepRequest) HEAD(url string) *StepRequestWithOptionalArgs {
|
||||||
if s.Request != nil {
|
if s.Request != nil {
|
||||||
s.Request.Method = httpHEAD
|
s.Request.Method = HTTP_HEAD
|
||||||
s.Request.URL = url
|
s.Request.URL = url
|
||||||
} else {
|
} else {
|
||||||
s.Request = &Request{
|
s.Request = &Request{
|
||||||
Method: httpHEAD,
|
Method: HTTP_HEAD,
|
||||||
URL: url,
|
URL: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,11 +598,11 @@ func (s *StepRequest) HEAD(url string) *StepRequestWithOptionalArgs {
|
|||||||
// POST makes a HTTP POST request.
|
// POST makes a HTTP POST request.
|
||||||
func (s *StepRequest) POST(url string) *StepRequestWithOptionalArgs {
|
func (s *StepRequest) POST(url string) *StepRequestWithOptionalArgs {
|
||||||
if s.Request != nil {
|
if s.Request != nil {
|
||||||
s.Request.Method = httpPOST
|
s.Request.Method = HTTP_POST
|
||||||
s.Request.URL = url
|
s.Request.URL = url
|
||||||
} else {
|
} else {
|
||||||
s.Request = &Request{
|
s.Request = &Request{
|
||||||
Method: httpPOST,
|
Method: HTTP_POST,
|
||||||
URL: url,
|
URL: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -614,11 +614,11 @@ func (s *StepRequest) POST(url string) *StepRequestWithOptionalArgs {
|
|||||||
// PUT makes a HTTP PUT request.
|
// PUT makes a HTTP PUT request.
|
||||||
func (s *StepRequest) PUT(url string) *StepRequestWithOptionalArgs {
|
func (s *StepRequest) PUT(url string) *StepRequestWithOptionalArgs {
|
||||||
if s.Request != nil {
|
if s.Request != nil {
|
||||||
s.Request.Method = httpPUT
|
s.Request.Method = HTTP_PUT
|
||||||
s.Request.URL = url
|
s.Request.URL = url
|
||||||
} else {
|
} else {
|
||||||
s.Request = &Request{
|
s.Request = &Request{
|
||||||
Method: httpPUT,
|
Method: HTTP_PUT,
|
||||||
URL: url,
|
URL: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -630,11 +630,11 @@ func (s *StepRequest) PUT(url string) *StepRequestWithOptionalArgs {
|
|||||||
// DELETE makes a HTTP DELETE request.
|
// DELETE makes a HTTP DELETE request.
|
||||||
func (s *StepRequest) DELETE(url string) *StepRequestWithOptionalArgs {
|
func (s *StepRequest) DELETE(url string) *StepRequestWithOptionalArgs {
|
||||||
if s.Request != nil {
|
if s.Request != nil {
|
||||||
s.Request.Method = httpDELETE
|
s.Request.Method = HTTP_DELETE
|
||||||
s.Request.URL = url
|
s.Request.URL = url
|
||||||
} else {
|
} else {
|
||||||
s.Request = &Request{
|
s.Request = &Request{
|
||||||
Method: httpDELETE,
|
Method: HTTP_DELETE,
|
||||||
URL: url,
|
URL: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -646,11 +646,11 @@ func (s *StepRequest) DELETE(url string) *StepRequestWithOptionalArgs {
|
|||||||
// OPTIONS makes a HTTP OPTIONS request.
|
// OPTIONS makes a HTTP OPTIONS request.
|
||||||
func (s *StepRequest) OPTIONS(url string) *StepRequestWithOptionalArgs {
|
func (s *StepRequest) OPTIONS(url string) *StepRequestWithOptionalArgs {
|
||||||
if s.Request != nil {
|
if s.Request != nil {
|
||||||
s.Request.Method = httpOPTIONS
|
s.Request.Method = HTTP_OPTIONS
|
||||||
s.Request.URL = url
|
s.Request.URL = url
|
||||||
} else {
|
} else {
|
||||||
s.Request = &Request{
|
s.Request = &Request{
|
||||||
Method: httpOPTIONS,
|
Method: HTTP_OPTIONS,
|
||||||
URL: url,
|
URL: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -662,11 +662,11 @@ func (s *StepRequest) OPTIONS(url string) *StepRequestWithOptionalArgs {
|
|||||||
// PATCH makes a HTTP PATCH request.
|
// PATCH makes a HTTP PATCH request.
|
||||||
func (s *StepRequest) PATCH(url string) *StepRequestWithOptionalArgs {
|
func (s *StepRequest) PATCH(url string) *StepRequestWithOptionalArgs {
|
||||||
if s.Request != nil {
|
if s.Request != nil {
|
||||||
s.Request.Method = httpPATCH
|
s.Request.Method = HTTP_PATCH
|
||||||
s.Request.URL = url
|
s.Request.URL = url
|
||||||
} else {
|
} else {
|
||||||
s.Request = &Request{
|
s.Request = &Request{
|
||||||
Method: httpPATCH,
|
Method: HTTP_PATCH,
|
||||||
URL: url,
|
URL: url,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
package hrp
|
|
||||||
+5
-5
@@ -42,14 +42,14 @@ func (s *StepThinkTime) Run(r *SessionRunner) (*StepResult, error) {
|
|||||||
|
|
||||||
cfg := r.caseRunner.Config.Get().ThinkTimeSetting
|
cfg := r.caseRunner.Config.Get().ThinkTimeSetting
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
cfg = &ThinkTimeConfig{thinkTimeDefault, nil, 0}
|
cfg = &ThinkTimeConfig{ThinkTimeDefault, nil, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
var tt time.Duration
|
var tt time.Duration
|
||||||
switch cfg.Strategy {
|
switch cfg.Strategy {
|
||||||
case thinkTimeDefault:
|
case ThinkTimeDefault:
|
||||||
tt = time.Duration(thinkTime.Time*1000) * time.Millisecond
|
tt = time.Duration(thinkTime.Time*1000) * time.Millisecond
|
||||||
case thinkTimeRandomPercentage:
|
case ThinkTimeRandomPercentage:
|
||||||
// e.g. {"min_percentage": 0.5, "max_percentage": 1.5}
|
// e.g. {"min_percentage": 0.5, "max_percentage": 1.5}
|
||||||
m, ok := cfg.Setting.(map[string]float64)
|
m, ok := cfg.Setting.(map[string]float64)
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -58,13 +58,13 @@ func (s *StepThinkTime) Run(r *SessionRunner) (*StepResult, error) {
|
|||||||
}
|
}
|
||||||
res := builtin.GetRandomNumber(int(thinkTime.Time*m["min_percentage"]*1000), int(thinkTime.Time*m["max_percentage"]*1000))
|
res := builtin.GetRandomNumber(int(thinkTime.Time*m["min_percentage"]*1000), int(thinkTime.Time*m["max_percentage"]*1000))
|
||||||
tt = time.Duration(res) * time.Millisecond
|
tt = time.Duration(res) * time.Millisecond
|
||||||
case thinkTimeMultiply:
|
case ThinkTimeMultiply:
|
||||||
value, ok := cfg.Setting.(float64) // e.g. 0.5
|
value, ok := cfg.Setting.(float64) // e.g. 0.5
|
||||||
if !ok || value <= 0 {
|
if !ok || value <= 0 {
|
||||||
value = thinkTimeDefaultMultiply
|
value = thinkTimeDefaultMultiply
|
||||||
}
|
}
|
||||||
tt = time.Duration(thinkTime.Time*value*1000) * time.Millisecond
|
tt = time.Duration(thinkTime.Time*value*1000) * time.Millisecond
|
||||||
case thinkTimeIgnore:
|
case ThinkTimeIgnore:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
|
"github.com/httprunner/httprunner/v5/internal/builtin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRun(t *testing.T) {
|
||||||
|
err := hrp.BuildPlugin(tmpl("plugin/debugtalk.go"), "./debugtalk.bin")
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
genDebugTalkPyPath := filepath.Join(tmpl("plugin/"), hrp.PluginPySourceGenFile)
|
||||||
|
err = hrp.BuildPlugin(tmpl("plugin/debugtalk.py"), genDebugTalkPyPath)
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
contentBytes, err := builtin.LoadFile(genDebugTalkPyPath)
|
||||||
|
if !assert.Nil(t, err) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
content := string(contentBytes)
|
||||||
|
if !assert.Contains(t, content, "import funppy") {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !assert.Contains(t, content, "funppy.register") {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
reg, _ := regexp.Compile(`funppy\.register`)
|
||||||
|
matchedSlice := reg.FindAllStringSubmatch(content, -1)
|
||||||
|
if !assert.Len(t, matchedSlice, 10) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadTestCases(t *testing.T) {
|
func TestLoadTestCases(t *testing.T) {
|
||||||
// load test cases from folder path
|
// load test cases from folder path
|
||||||
tc := TestCasePath("../examples/demo-with-py-plugin/testcases/")
|
tc := hrp.TestCasePath("../examples/demo-with-py-plugin/testcases/")
|
||||||
testCases, err := LoadTestCases(&tc)
|
testCases, err := hrp.LoadTestCases(&tc)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -18,8 +20,8 @@ func TestLoadTestCases(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load test cases from folder path, including sub folders
|
// load test cases from folder path, including sub folders
|
||||||
tc = TestCasePath("../examples/demo-with-py-plugin/")
|
tc = hrp.TestCasePath("../examples/demo-with-py-plugin/")
|
||||||
testCases, err = LoadTestCases(&tc)
|
testCases, err = hrp.LoadTestCases(&tc)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -28,8 +30,8 @@ func TestLoadTestCases(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load test cases from single file path
|
// load test cases from single file path
|
||||||
tc = TestCasePath(demoTestCaseWithPluginJSONPath)
|
tc = hrp.TestCasePath(demoTestCaseWithPluginJSONPath)
|
||||||
testCases, err = LoadTestCases(&tc)
|
testCases, err = hrp.LoadTestCases(&tc)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -38,10 +40,10 @@ func TestLoadTestCases(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load test cases from TestCase instance
|
// load test cases from TestCase instance
|
||||||
testcase := &TestCase{
|
testcase := &hrp.TestCase{
|
||||||
Config: NewConfig("TestCase").SetWeight(3),
|
Config: hrp.NewConfig("TestCase").SetWeight(3),
|
||||||
}
|
}
|
||||||
testCases, err = LoadTestCases(testcase)
|
testCases, err = hrp.LoadTestCases(testcase)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -50,7 +52,7 @@ func TestLoadTestCases(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load test cases from TestCaseJSON
|
// load test cases from TestCaseJSON
|
||||||
testcaseJSON := TestCaseJSON(`
|
testcaseJSON := hrp.TestCaseJSON(`
|
||||||
{
|
{
|
||||||
"config":{"name":"TestCaseJSON"},
|
"config":{"name":"TestCaseJSON"},
|
||||||
"teststeps":[
|
"teststeps":[
|
||||||
@@ -58,7 +60,7 @@ func TestLoadTestCases(t *testing.T) {
|
|||||||
{"name": "step2", "shell":{"string": "ls -l"}}
|
{"name": "step2", "shell":{"string": "ls -l"}}
|
||||||
]
|
]
|
||||||
}`)
|
}`)
|
||||||
testCases, err = LoadTestCases(&testcaseJSON)
|
testCases, err = hrp.LoadTestCases(&testcaseJSON)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -68,13 +70,13 @@ func TestLoadTestCases(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadCase(t *testing.T) {
|
func TestLoadCase(t *testing.T) {
|
||||||
tcJSON := &TestCaseDef{}
|
tcJSON := &hrp.TestCaseDef{}
|
||||||
tcYAML := &TestCaseDef{}
|
tcYAML := &hrp.TestCaseDef{}
|
||||||
err := LoadFileObject(demoTestCaseWithPluginJSONPath, tcJSON)
|
err := hrp.LoadFileObject(demoTestCaseWithPluginJSONPath, tcJSON)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
err = LoadFileObject(demoTestCaseWithPluginYAMLPath, tcYAML)
|
err = hrp.LoadFileObject(demoTestCaseWithPluginYAMLPath, tcYAML)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadParameters(t *testing.T) {
|
func TestLoadParameters(t *testing.T) {
|
||||||
testData := []struct {
|
testData := []struct {
|
||||||
configParameters map[string]interface{}
|
configParameters map[string]interface{}
|
||||||
loadedParameters map[string]Parameters
|
loadedParameters map[string]hrp.Parameters
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"username-password": fmt.Sprintf("${parameterize(%s/$file)}", hrpExamplesDir),
|
"username-password": fmt.Sprintf("${parameterize(%s/$file)}", hrpExamplesDir),
|
||||||
},
|
},
|
||||||
map[string]Parameters{
|
map[string]hrp.Parameters{
|
||||||
"username-password": {
|
"username-password": {
|
||||||
{"username": "test1", "password": "111111"},
|
{"username": "test1", "password": "111111"},
|
||||||
{"username": "test2", "password": "222222"},
|
{"username": "test2", "password": "222222"},
|
||||||
@@ -33,7 +35,7 @@ func TestLoadParameters(t *testing.T) {
|
|||||||
"user_agent": []interface{}{"iOS/10.1", "iOS/10.2"},
|
"user_agent": []interface{}{"iOS/10.1", "iOS/10.2"},
|
||||||
"app_version": []interface{}{4.0},
|
"app_version": []interface{}{4.0},
|
||||||
},
|
},
|
||||||
map[string]Parameters{
|
map[string]hrp.Parameters{
|
||||||
"username-password": {
|
"username-password": {
|
||||||
{"username": "test1", "password": "111111"},
|
{"username": "test1", "password": "111111"},
|
||||||
{"username": "test2", "password": "222222"},
|
{"username": "test2", "password": "222222"},
|
||||||
@@ -54,7 +56,7 @@ func TestLoadParameters(t *testing.T) {
|
|||||||
[]interface{}{"test2", "222222"},
|
[]interface{}{"test2", "222222"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
map[string]Parameters{
|
map[string]hrp.Parameters{
|
||||||
"username-password": {
|
"username-password": {
|
||||||
{"username": "test1", "password": "111111"},
|
{"username": "test1", "password": "111111"},
|
||||||
{"username": "test2", "password": "222222"},
|
{"username": "test2", "password": "222222"},
|
||||||
@@ -74,9 +76,9 @@ func TestLoadParameters(t *testing.T) {
|
|||||||
variablesMapping := map[string]interface{}{
|
variablesMapping := map[string]interface{}{
|
||||||
"file": "account.csv",
|
"file": "account.csv",
|
||||||
}
|
}
|
||||||
parser := newParser()
|
parser := hrp.NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
value, err := parser.loadParameters(data.configParameters, variablesMapping)
|
value, err := parser.LoadParameters(data.configParameters, variablesMapping)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -109,9 +111,9 @@ func TestLoadParametersError(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
parser := newParser()
|
parser := hrp.NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
_, err := parser.loadParameters(data.configParameters, map[string]interface{}{})
|
_, err := parser.LoadParameters(data.configParameters, map[string]interface{}{})
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -125,28 +127,28 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
"app_version": []interface{}{4.0}, // 1
|
"app_version": []interface{}{4.0}, // 1
|
||||||
}
|
}
|
||||||
testData := []struct {
|
testData := []struct {
|
||||||
cfg *TConfig
|
cfg *hrp.TConfig
|
||||||
expectLimit int
|
expectLimit int
|
||||||
}{
|
}{
|
||||||
// default, no parameters setting
|
// default, no parameters setting
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{},
|
ParametersSetting: &hrp.TParamsConfig{},
|
||||||
},
|
},
|
||||||
6, // 3 * 2 * 1
|
6, // 3 * 2 * 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
},
|
},
|
||||||
6, // 3 * 2 * 1
|
6, // 3 * 2 * 1
|
||||||
},
|
},
|
||||||
// default equals to set overall parameters pick-order to "sequential"
|
// default equals to set overall parameters pick-order to "sequential"
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
PickOrder: "sequential",
|
PickOrder: "sequential",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -154,10 +156,10 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
},
|
},
|
||||||
// default equals to set each individual parameters pick-order to "sequential"
|
// default equals to set each individual parameters pick-order to "sequential"
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
Strategies: map[string]iteratorStrategy{
|
Strategies: map[string]hrp.IteratorStrategy{
|
||||||
"username-password": {Name: "user-info", PickOrder: "sequential"},
|
"username-password": {Name: "user-info", PickOrder: "sequential"},
|
||||||
"user_agent": {Name: "user-identity", PickOrder: "sequential"},
|
"user_agent": {Name: "user-identity", PickOrder: "sequential"},
|
||||||
"app_version": {Name: "app-version", PickOrder: "sequential"},
|
"app_version": {Name: "app-version", PickOrder: "sequential"},
|
||||||
@@ -167,10 +169,10 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
6, // 3 * 2 * 1
|
6, // 3 * 2 * 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
Strategies: map[string]iteratorStrategy{
|
Strategies: map[string]hrp.IteratorStrategy{
|
||||||
"user_agent": {Name: "user-identity", PickOrder: "sequential"},
|
"user_agent": {Name: "user-identity", PickOrder: "sequential"},
|
||||||
"app_version": {Name: "app-version", PickOrder: "sequential"},
|
"app_version": {Name: "app-version", PickOrder: "sequential"},
|
||||||
},
|
},
|
||||||
@@ -182,9 +184,9 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
// set overall parameters overall pick-order to "random"
|
// set overall parameters overall pick-order to "random"
|
||||||
// each random parameters only select one item
|
// each random parameters only select one item
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
PickOrder: "random",
|
PickOrder: "random",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -193,10 +195,10 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
// set some individual parameters pick-order to "random"
|
// set some individual parameters pick-order to "random"
|
||||||
// this will override overall strategy
|
// this will override overall strategy
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
Strategies: map[string]iteratorStrategy{
|
Strategies: map[string]hrp.IteratorStrategy{
|
||||||
"user_agent": {Name: "user-identity", PickOrder: "random"},
|
"user_agent": {Name: "user-identity", PickOrder: "random"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -204,10 +206,10 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
3, // 3 * 1 * 1
|
3, // 3 * 1 * 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
Strategies: map[string]iteratorStrategy{
|
Strategies: map[string]hrp.IteratorStrategy{
|
||||||
"username-password": {Name: "user-info", PickOrder: "random"},
|
"username-password": {Name: "user-info", PickOrder: "random"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -217,18 +219,18 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
|
|
||||||
// set limit for parameters
|
// set limit for parameters
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters, // total: 6 = 3 * 2 * 1
|
Parameters: configParameters, // total: 6 = 3 * 2 * 1
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
Limit: 4, // limit could be less than total
|
Limit: 4, // limit could be less than total
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
4,
|
4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters, // total: 6 = 3 * 2 * 1
|
Parameters: configParameters, // total: 6 = 3 * 2 * 1
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
Limit: 9, // limit could also be greater than total
|
Limit: 9, // limit could also be greater than total
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -238,20 +240,20 @@ func TestInitParametersIteratorCount(t *testing.T) {
|
|||||||
// no parameters
|
// no parameters
|
||||||
// also will generate one empty item
|
// also will generate one empty item
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: nil,
|
Parameters: nil,
|
||||||
ParametersSetting: nil,
|
ParametersSetting: nil,
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
parser := newParser()
|
parser := hrp.NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
iterator, err := parser.initParametersIterator(data.cfg)
|
iterator, err := parser.InitParametersIterator(data.cfg)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, data.expectLimit, iterator.limit) {
|
if !assert.Equal(t, data.expectLimit, iterator.Limit) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,34 +277,34 @@ func TestInitParametersIteratorUnlimitedCount(t *testing.T) {
|
|||||||
"app_version": []interface{}{4.0}, // 1
|
"app_version": []interface{}{4.0}, // 1
|
||||||
}
|
}
|
||||||
testData := []struct {
|
testData := []struct {
|
||||||
cfg *TConfig
|
cfg *hrp.TConfig
|
||||||
}{
|
}{
|
||||||
// default, no parameters setting
|
// default, no parameters setting
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
ParametersSetting: &TParamsConfig{},
|
ParametersSetting: &hrp.TParamsConfig{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// no parameters
|
// no parameters
|
||||||
// also will generate one empty item
|
// also will generate one empty item
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: nil,
|
Parameters: nil,
|
||||||
ParametersSetting: nil,
|
ParametersSetting: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
parser := newParser()
|
parser := hrp.NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
iterator, err := parser.initParametersIterator(data.cfg)
|
iterator, err := parser.InitParametersIterator(data.cfg)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
// set unlimited mode
|
// set unlimited mode
|
||||||
iterator.SetUnlimitedMode()
|
iterator.SetUnlimitedMode()
|
||||||
if !assert.Equal(t, -1, iterator.limit) {
|
if !assert.Equal(t, -1, iterator.Limit) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +314,7 @@ func TestInitParametersIteratorUnlimitedCount(t *testing.T) {
|
|||||||
}
|
}
|
||||||
iterator.Next() // consume next parameters
|
iterator.Next() // consume next parameters
|
||||||
}
|
}
|
||||||
if !assert.Equal(t, 100, iterator.index) {
|
if !assert.Equal(t, 100, iterator.Index) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
// should also have next
|
// should also have next
|
||||||
@@ -329,13 +331,13 @@ func TestInitParametersIteratorContent(t *testing.T) {
|
|||||||
"app_version": []interface{}{4.0}, // 1
|
"app_version": []interface{}{4.0}, // 1
|
||||||
}
|
}
|
||||||
testData := []struct {
|
testData := []struct {
|
||||||
cfg *TConfig
|
cfg *hrp.TConfig
|
||||||
checkIndex int
|
checkIndex int
|
||||||
expectParameters map[string]interface{}
|
expectParameters map[string]interface{}
|
||||||
}{
|
}{
|
||||||
// default, no parameters setting
|
// default, no parameters setting
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: configParameters,
|
Parameters: configParameters,
|
||||||
},
|
},
|
||||||
0, // check first item
|
0, // check first item
|
||||||
@@ -346,16 +348,16 @@ func TestInitParametersIteratorContent(t *testing.T) {
|
|||||||
|
|
||||||
// set limit for parameters
|
// set limit for parameters
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: map[string]interface{}{
|
Parameters: map[string]interface{}{
|
||||||
"username-password": []map[string]interface{}{ // 1
|
"username-password": []map[string]interface{}{ // 1
|
||||||
{"username": "test1", "password": 111111, "other": "111"},
|
{"username": "test1", "password": 111111, "other": "111"},
|
||||||
},
|
},
|
||||||
"user_agent": []string{"iOS/10.1", "iOS/10.2"}, // 2
|
"user_agent": []string{"iOS/10.1", "iOS/10.2"}, // 2
|
||||||
},
|
},
|
||||||
ParametersSetting: &TParamsConfig{
|
ParametersSetting: &hrp.TParamsConfig{
|
||||||
Limit: 5, // limit could also be greater than total
|
Limit: 5, // limit could also be greater than total
|
||||||
Strategies: map[string]iteratorStrategy{
|
Strategies: map[string]hrp.IteratorStrategy{
|
||||||
"username-password": {Name: "user-info", PickOrder: "random"},
|
"username-password": {Name: "user-info", PickOrder: "random"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -369,7 +371,7 @@ func TestInitParametersIteratorContent(t *testing.T) {
|
|||||||
// no parameters
|
// no parameters
|
||||||
// also will generate one empty item
|
// also will generate one empty item
|
||||||
{
|
{
|
||||||
&TConfig{
|
&hrp.TConfig{
|
||||||
Parameters: nil,
|
Parameters: nil,
|
||||||
ParametersSetting: nil,
|
ParametersSetting: nil,
|
||||||
},
|
},
|
||||||
@@ -377,9 +379,9 @@ func TestInitParametersIteratorContent(t *testing.T) {
|
|||||||
map[string]interface{}{},
|
map[string]interface{}{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
parser := newParser()
|
parser := hrp.NewParser()
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
iterator, err := parser.initParametersIterator(data.cfg)
|
iterator, err := parser.InitParametersIterator(data.cfg)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -401,11 +403,11 @@ func TestInitParametersIteratorContent(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenCartesianProduct(t *testing.T) {
|
func TestGenCartesianProduct(t *testing.T) {
|
||||||
testData := []struct {
|
testData := []struct {
|
||||||
multiParameters []Parameters
|
multiParameters []hrp.Parameters
|
||||||
expect Parameters
|
expect hrp.Parameters
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
[]Parameters{
|
[]hrp.Parameters{
|
||||||
{
|
{
|
||||||
{"app_version": 4.0},
|
{"app_version": 4.0},
|
||||||
},
|
},
|
||||||
@@ -418,7 +420,7 @@ func TestGenCartesianProduct(t *testing.T) {
|
|||||||
{"user_agent": "iOS/10.2"},
|
{"user_agent": "iOS/10.2"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Parameters{
|
hrp.Parameters{
|
||||||
{"app_version": 4.0, "password": "111111", "user_agent": "iOS/10.1", "username": "test1"},
|
{"app_version": 4.0, "password": "111111", "user_agent": "iOS/10.1", "username": "test1"},
|
||||||
{"app_version": 4.0, "password": "111111", "user_agent": "iOS/10.2", "username": "test1"},
|
{"app_version": 4.0, "password": "111111", "user_agent": "iOS/10.2", "username": "test1"},
|
||||||
{"app_version": 4.0, "password": "222222", "user_agent": "iOS/10.1", "username": "test2"},
|
{"app_version": 4.0, "password": "222222", "user_agent": "iOS/10.1", "username": "test2"},
|
||||||
@@ -430,13 +432,13 @@ func TestGenCartesianProduct(t *testing.T) {
|
|||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
[]Parameters{},
|
[]hrp.Parameters{},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
parameters := genCartesianProduct(data.multiParameters)
|
parameters := hrp.GenCartesianProduct(data.multiParameters)
|
||||||
if !assert.Equal(t, data.expect, parameters) {
|
if !assert.Equal(t, data.expect, parameters) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -490,7 +492,7 @@ func TestConvertParameters(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
value, err := convertParameters(data.key, data.parametersRawList)
|
value, err := hrp.ConvertParameters(data.key, data.parametersRawList)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -530,7 +532,7 @@ func TestConvertParametersError(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, data := range testData {
|
for _, data := range testData {
|
||||||
_, err := convertParameters(data.key, data.parametersRawList)
|
_, err := hrp.ConvertParameters(data.key, data.parametersRawList)
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,45 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLocateFile(t *testing.T) {
|
func TestLocateFile(t *testing.T) {
|
||||||
// specify target file path
|
// specify target file path
|
||||||
_, err := locateFile(tmpl("plugin/debugtalk.go"), PluginGoSourceFile)
|
_, err := hrp.LocateFile(tmpl("plugin/debugtalk.go"), hrp.PluginGoSourceFile)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
// specify path with the same dir
|
// specify path with the same dir
|
||||||
_, err = locateFile(tmpl("plugin/debugtalk.py"), PluginGoSourceFile)
|
_, err = hrp.LocateFile(tmpl("plugin/debugtalk.py"), hrp.PluginGoSourceFile)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
// specify target file path dir
|
// specify target file path dir
|
||||||
_, err = locateFile(tmpl("plugin/"), PluginGoSourceFile)
|
_, err = hrp.LocateFile(tmpl("plugin/"), hrp.PluginGoSourceFile)
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
// specify wrong path
|
// specify wrong path
|
||||||
_, err = locateFile(".", PluginGoSourceFile)
|
_, err = hrp.LocateFile(".", hrp.PluginGoSourceFile)
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
_, err = locateFile("/abc", PluginGoSourceFile)
|
_, err = hrp.LocateFile("/abc", hrp.PluginGoSourceFile)
|
||||||
if !assert.Error(t, err) {
|
if !assert.Error(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocatePythonPlugin(t *testing.T) {
|
func TestLocatePythonPlugin(t *testing.T) {
|
||||||
_, err := locatePlugin(tmpl("plugin/debugtalk.py"))
|
_, err := hrp.LocatePlugin(tmpl("plugin/debugtalk.py"))
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -47,7 +49,7 @@ func TestLocateGoPlugin(t *testing.T) {
|
|||||||
buildHashicorpGoPlugin()
|
buildHashicorpGoPlugin()
|
||||||
defer removeHashicorpGoPlugin()
|
defer removeHashicorpGoPlugin()
|
||||||
|
|
||||||
_, err := locatePlugin(tmpl("debugtalk.bin"))
|
_, err := hrp.LocatePlugin(tmpl("debugtalk.bin"))
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
"github.com/httprunner/httprunner/v5/code"
|
"github.com/httprunner/httprunner/v5/code"
|
||||||
)
|
)
|
||||||
|
|
||||||
func buildHashicorpGoPlugin() {
|
func buildHashicorpGoPlugin() {
|
||||||
log.Info().Msg("[init] build hashicorp go plugin")
|
log.Info().Msg("[init] build hashicorp go plugin")
|
||||||
err := BuildPlugin(tmpl("plugin/debugtalk.go"), tmpl("debugtalk.bin"))
|
err := hrp.BuildPlugin(tmpl("plugin/debugtalk.go"), tmpl("debugtalk.bin"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("build hashicorp go plugin failed")
|
log.Error().Err(err).Msg("build hashicorp go plugin failed")
|
||||||
os.Exit(code.GetErrorCode(err))
|
os.Exit(code.GetErrorCode(err))
|
||||||
@@ -26,8 +26,6 @@ func buildHashicorpGoPlugin() {
|
|||||||
func removeHashicorpGoPlugin() {
|
func removeHashicorpGoPlugin() {
|
||||||
log.Info().Msg("[teardown] remove hashicorp go plugin")
|
log.Info().Msg("[teardown] remove hashicorp go plugin")
|
||||||
os.Remove(tmpl("debugtalk.bin"))
|
os.Remove(tmpl("debugtalk.bin"))
|
||||||
pluginPath, _ := filepath.Abs(tmpl("debugtalk.bin"))
|
|
||||||
pluginMap.Delete(pluginPath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildHashicorpPyPlugin() {
|
func buildHashicorpPyPlugin() {
|
||||||
@@ -43,8 +41,8 @@ func buildHashicorpPyPlugin() {
|
|||||||
func removeHashicorpPyPlugin() {
|
func removeHashicorpPyPlugin() {
|
||||||
log.Info().Msg("[teardown] remove hashicorp python plugin")
|
log.Info().Msg("[teardown] remove hashicorp python plugin")
|
||||||
// on v4.1^, running case will generate .debugtalk_gen.py used by python plugin
|
// on v4.1^, running case will generate .debugtalk_gen.py used by python plugin
|
||||||
os.Remove(tmpl(PluginPySourceFile))
|
os.Remove(tmpl(hrp.PluginPySourceFile))
|
||||||
os.Remove(tmpl(PluginPySourceGenFile))
|
os.Remove(tmpl(hrp.PluginPySourceGenFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunCaseWithGoPlugin(t *testing.T) {
|
func TestRunCaseWithGoPlugin(t *testing.T) {
|
||||||
@@ -62,21 +60,21 @@ func TestRunCaseWithPythonPlugin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func assertRunTestCases(t *testing.T) {
|
func assertRunTestCases(t *testing.T) {
|
||||||
refCase := TestCasePath(demoTestCaseWithPluginJSONPath)
|
refCase := hrp.TestCasePath(demoTestCaseWithPluginJSONPath)
|
||||||
testcase1 := &TestCase{
|
testcase1 := &hrp.TestCase{
|
||||||
Config: NewConfig("TestCase1").
|
Config: hrp.NewConfig("TestCase1").
|
||||||
SetBaseURL("https://postman-echo.com"),
|
SetBaseURL("https://postman-echo.com"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("testcase1-step1").
|
hrp.NewStep("testcase1-step1").
|
||||||
GET("/headers").
|
GET("/headers").
|
||||||
Validate().
|
Validate().
|
||||||
AssertEqual("status_code", 200, "check status code").
|
AssertEqual("status_code", 200, "check status code").
|
||||||
AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check http response Content-Type"),
|
AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check http response Content-Type"),
|
||||||
NewStep("testcase1-step2").CallRefCase(
|
hrp.NewStep("testcase1-step2").CallRefCase(
|
||||||
&TestCase{
|
&hrp.TestCase{
|
||||||
Config: NewConfig("testcase1-step3-ref-case").SetBaseURL("https://postman-echo.com"),
|
Config: hrp.NewConfig("testcase1-step3-ref-case").SetBaseURL("https://postman-echo.com"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("ip").
|
hrp.NewStep("ip").
|
||||||
GET("/ip").
|
GET("/ip").
|
||||||
Validate().
|
Validate().
|
||||||
AssertEqual("status_code", 200, "check status code").
|
AssertEqual("status_code", 200, "check status code").
|
||||||
@@ -84,14 +82,14 @@ func assertRunTestCases(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
NewStep("testcase1-step3").CallRefCase(&refCase),
|
hrp.NewStep("testcase1-step3").CallRefCase(&refCase),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
testcase2 := &TestCase{
|
testcase2 := &hrp.TestCase{
|
||||||
Config: NewConfig("TestCase2").SetWeight(3),
|
Config: hrp.NewConfig("TestCase2").SetWeight(3),
|
||||||
}
|
}
|
||||||
|
|
||||||
r := NewRunner(t)
|
r := hrp.NewRunner(t)
|
||||||
r.SetPluginLogOn()
|
r.SetPluginLogOn()
|
||||||
err := r.Run(testcase1, testcase2)
|
err := r.Run(testcase1, testcase2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -103,46 +101,46 @@ func TestRunCaseWithThinkTime(t *testing.T) {
|
|||||||
buildHashicorpGoPlugin()
|
buildHashicorpGoPlugin()
|
||||||
defer removeHashicorpGoPlugin()
|
defer removeHashicorpGoPlugin()
|
||||||
|
|
||||||
testcases := []*TestCase{
|
testcases := []*hrp.TestCase{
|
||||||
{
|
{
|
||||||
Config: NewConfig("TestCase1"),
|
Config: hrp.NewConfig("TestCase1"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("thinkTime").SetThinkTime(2),
|
hrp.NewStep("thinkTime").SetThinkTime(2),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Config: NewConfig("TestCase2").
|
Config: hrp.NewConfig("TestCase2").
|
||||||
SetThinkTime(thinkTimeIgnore, nil, 0),
|
SetThinkTime(hrp.ThinkTimeIgnore, nil, 0),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("thinkTime").SetThinkTime(0.5),
|
hrp.NewStep("thinkTime").SetThinkTime(0.5),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Config: NewConfig("TestCase3").
|
Config: hrp.NewConfig("TestCase3").
|
||||||
SetThinkTime(thinkTimeRandomPercentage, nil, 0),
|
SetThinkTime(hrp.ThinkTimeRandomPercentage, nil, 0),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("thinkTime").SetThinkTime(1),
|
hrp.NewStep("thinkTime").SetThinkTime(1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Config: NewConfig("TestCase4").
|
Config: hrp.NewConfig("TestCase4").
|
||||||
SetThinkTime(thinkTimeRandomPercentage, map[string]interface{}{"min_percentage": 2, "max_percentage": 3}, 2.5),
|
SetThinkTime(hrp.ThinkTimeRandomPercentage, map[string]interface{}{"min_percentage": 2, "max_percentage": 3}, 2.5),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("thinkTime").SetThinkTime(1),
|
hrp.NewStep("thinkTime").SetThinkTime(1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Config: NewConfig("TestCase5"),
|
Config: hrp.NewConfig("TestCase5"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
// 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),
|
hrp.NewStep("thinkTime").CallRefCase(&demoTestCaseWithThinkTimePath),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
expectedMinValue := []float64{2, 0, 0.5, 2, 3}
|
expectedMinValue := []float64{2, 0, 0.5, 2, 3}
|
||||||
expectedMaxValue := []float64{2.5, 0.5, 2, 3, 10}
|
expectedMaxValue := []float64{2.5, 0.5, 2, 3, 10}
|
||||||
for idx, testcase := range testcases {
|
for idx, testcase := range testcases {
|
||||||
r := NewRunner(t)
|
r := hrp.NewRunner(t)
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
err := r.Run(testcase)
|
err := r.Run(testcase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -158,20 +156,20 @@ func TestRunCaseWithThinkTime(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunCaseWithShell(t *testing.T) {
|
func TestRunCaseWithShell(t *testing.T) {
|
||||||
testcase1 := &TestCase{
|
testcase1 := &hrp.TestCase{
|
||||||
Config: NewConfig("complex shell with env variables").
|
Config: hrp.NewConfig("complex shell with env variables").
|
||||||
WithVariables(map[string]interface{}{
|
WithVariables(map[string]interface{}{
|
||||||
"SS": "12345",
|
"SS": "12345",
|
||||||
"ABC": "$SS",
|
"ABC": "$SS",
|
||||||
}),
|
}),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("shell21").Shell("echo hello world"),
|
hrp.NewStep("shell21").Shell("echo hello world"),
|
||||||
// NewStep("shell21").Shell("echo $ABC"),
|
// NewStep("shell21").Shell("echo $ABC"),
|
||||||
// NewStep("shell21").Shell("which hrp"),
|
// NewStep("shell21").Shell("which hrp"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
r := NewRunner(t)
|
r := hrp.NewRunner(t)
|
||||||
err := r.Run(testcase1)
|
err := r.Run(testcase1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
@@ -193,16 +191,16 @@ func TestRunCaseWithFunction(t *testing.T) {
|
|||||||
err3 = errors.New("func3 error")
|
err3 = errors.New("func3 error")
|
||||||
fmt.Println("call function3 with return value and error")
|
fmt.Println("call function3 with return value and error")
|
||||||
}
|
}
|
||||||
testcase1 := &TestCase{
|
testcase1 := &hrp.TestCase{
|
||||||
Config: NewConfig("call function"),
|
Config: hrp.NewConfig("call function"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("fn1").Function(fn1),
|
hrp.NewStep("fn1").Function(fn1),
|
||||||
NewStep("fn2").Function(fn2),
|
hrp.NewStep("fn2").Function(fn2),
|
||||||
NewStep("fn3").Function(fn3),
|
hrp.NewStep("fn3").Function(fn3),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
r := NewRunner(t)
|
r := hrp.NewRunner(t)
|
||||||
err := r.Run(testcase1)
|
err := r.Run(testcase1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
@@ -220,8 +218,8 @@ func TestRunCaseWithPluginJSON(t *testing.T) {
|
|||||||
buildHashicorpGoPlugin()
|
buildHashicorpGoPlugin()
|
||||||
defer removeHashicorpGoPlugin()
|
defer removeHashicorpGoPlugin()
|
||||||
|
|
||||||
testCase := TestCasePath(demoTestCaseWithPluginJSONPath)
|
testCase := hrp.TestCasePath(demoTestCaseWithPluginJSONPath)
|
||||||
err := NewRunner(nil).Run(&testCase) // hrp.Run(testCase)
|
err := hrp.NewRunner(nil).Run(&testCase) // hrp.Run(testCase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -243,22 +241,22 @@ func TestRunCaseWithRefAPI(t *testing.T) {
|
|||||||
buildHashicorpGoPlugin()
|
buildHashicorpGoPlugin()
|
||||||
defer removeHashicorpGoPlugin()
|
defer removeHashicorpGoPlugin()
|
||||||
|
|
||||||
testCase := TestCasePath(demoTestCaseWithRefAPIPath)
|
testCase := hrp.TestCasePath(demoTestCaseWithRefAPIPath)
|
||||||
err := NewRunner(nil).Run(&testCase)
|
err := hrp.NewRunner(nil).Run(&testCase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
refAPI := APIPath(demoAPIGETPath)
|
refAPI := hrp.APIPath(demoAPIGETPath)
|
||||||
testcase := &TestCase{
|
testcase := &hrp.TestCase{
|
||||||
Config: NewConfig("TestCase").
|
Config: hrp.NewConfig("TestCase").
|
||||||
SetBaseURL("https://postman-echo.com"),
|
SetBaseURL("https://postman-echo.com"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("run referenced api").CallRefAPI(&refAPI),
|
hrp.NewStep("run referenced api").CallRefAPI(&refAPI),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
r := NewRunner(t)
|
r := hrp.NewRunner(t)
|
||||||
err = r.Run(testcase)
|
err = r.Run(testcase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
@@ -266,15 +264,15 @@ func TestRunCaseWithRefAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestSessionRunner(t *testing.T) {
|
func TestSessionRunner(t *testing.T) {
|
||||||
testcase := TestCase{
|
testcase := hrp.TestCase{
|
||||||
Config: NewConfig("TestCase").
|
Config: hrp.NewConfig("TestCase").
|
||||||
WithVariables(map[string]interface{}{
|
WithVariables(map[string]interface{}{
|
||||||
"a": 12.3,
|
"a": 12.3,
|
||||||
"b": 3.45,
|
"b": 3.45,
|
||||||
"varFoo": "${max($a, $b)}",
|
"varFoo": "${max($a, $b)}",
|
||||||
}),
|
}),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("check variables").
|
hrp.NewStep("check variables").
|
||||||
WithVariables(map[string]interface{}{
|
WithVariables(map[string]interface{}{
|
||||||
"a": 12.3,
|
"a": 12.3,
|
||||||
"b": 34.5,
|
"b": 34.5,
|
||||||
@@ -287,7 +285,7 @@ func TestSessionRunner(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
caseRunner, _ := NewRunner(t).NewCaseRunner(testcase)
|
caseRunner, _ := hrp.NewRunner(t).NewCaseRunner(testcase)
|
||||||
sessionRunner := caseRunner.NewSession()
|
sessionRunner := caseRunner.NewSession()
|
||||||
step := testcase.TestSteps[0]
|
step := testcase.TestSteps[0]
|
||||||
if !assert.Equal(t, step.Config().Variables["varFoo"], "${max($a, $b)}") {
|
if !assert.Equal(t, step.Config().Variables["varFoo"], "${max($a, $b)}") {
|
||||||
@@ -1,40 +1,42 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRunCaseWithRendezvous(t *testing.T) {
|
func TestRunCaseWithRendezvous(t *testing.T) {
|
||||||
rendezvousBoundaryTestcase := &TestCase{
|
rendezvousBoundaryTestcase := &hrp.TestCase{
|
||||||
Config: NewConfig("run request with functions").
|
Config: hrp.NewConfig("run request with functions").
|
||||||
SetBaseURL("https://postman-echo.com").
|
SetBaseURL("https://postman-echo.com").
|
||||||
WithVariables(map[string]interface{}{
|
WithVariables(map[string]interface{}{
|
||||||
"n": 5,
|
"n": 5,
|
||||||
"a": 12.3,
|
"a": 12.3,
|
||||||
"b": 3.45,
|
"b": 3.45,
|
||||||
}),
|
}),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("test negative number").
|
hrp.NewStep("test negative number").
|
||||||
SetRendezvous("test negative number").
|
SetRendezvous("test negative number").
|
||||||
WithUserNumber(-1),
|
WithUserNumber(-1),
|
||||||
NewStep("test overflow number").
|
hrp.NewStep("test overflow number").
|
||||||
SetRendezvous("test overflow number").
|
SetRendezvous("test overflow number").
|
||||||
WithUserNumber(1000000),
|
WithUserNumber(1000000),
|
||||||
NewStep("test negative percent").
|
hrp.NewStep("test negative percent").
|
||||||
SetRendezvous("test very low percent").
|
SetRendezvous("test very low percent").
|
||||||
WithUserPercent(-0.5),
|
WithUserPercent(-0.5),
|
||||||
NewStep("test very low percent").
|
hrp.NewStep("test very low percent").
|
||||||
SetRendezvous("test very low percent").
|
SetRendezvous("test very low percent").
|
||||||
WithUserPercent(0.00001),
|
WithUserPercent(0.00001),
|
||||||
NewStep("test overflow percent").
|
hrp.NewStep("test overflow percent").
|
||||||
SetRendezvous("test overflow percent").
|
SetRendezvous("test overflow percent").
|
||||||
WithUserPercent(1.5),
|
WithUserPercent(1.5),
|
||||||
NewStep("test conflict params").
|
hrp.NewStep("test conflict params").
|
||||||
SetRendezvous("test conflict params").
|
SetRendezvous("test conflict params").
|
||||||
WithUserNumber(1).
|
WithUserNumber(1).
|
||||||
WithUserPercent(0.123),
|
WithUserPercent(0.123),
|
||||||
NewStep("test negative timeout").
|
hrp.NewStep("test negative timeout").
|
||||||
SetRendezvous("test negative timeout").
|
SetRendezvous("test negative timeout").
|
||||||
WithTimeout(-1000),
|
WithTimeout(-1000),
|
||||||
},
|
},
|
||||||
@@ -55,7 +57,7 @@ func TestRunCaseWithRendezvous(t *testing.T) {
|
|||||||
{number: 100, percent: 1, timeout: 5000},
|
{number: 100, percent: 1, timeout: 5000},
|
||||||
}
|
}
|
||||||
|
|
||||||
rendezvousList := InitRendezvous(rendezvousBoundaryTestcase, 100)
|
rendezvousList := hrp.InitRendezvous(rendezvousBoundaryTestcase, 100)
|
||||||
|
|
||||||
for i, r := range rendezvousList {
|
for i, r := range rendezvousList {
|
||||||
if r.Number != expectedRendezvousParams[i].number {
|
if r.Number != expectedRendezvousParams[i].number {
|
||||||
@@ -1,17 +1,15 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
stepGET = NewStep("get with params").
|
stepGET = hrp.NewStep("get with params").
|
||||||
GET("/get").
|
GET("/get").
|
||||||
WithParams(map[string]interface{}{"foo1": "bar1", "foo2": "bar2"}).
|
WithParams(map[string]interface{}{"foo1": "bar1", "foo2": "bar2"}).
|
||||||
WithHeaders(map[string]string{"User-Agent": "HttpRunnerPlus"}).
|
WithHeaders(map[string]string{"User-Agent": "HttpRunnerPlus"}).
|
||||||
@@ -21,7 +19,7 @@ var (
|
|||||||
AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type").
|
AssertEqual("headers.\"Content-Type\"", "application/json; charset=utf-8", "check header Content-Type").
|
||||||
AssertEqual("body.args.foo1", "bar1", "check param foo1").
|
AssertEqual("body.args.foo1", "bar1", "check param foo1").
|
||||||
AssertEqual("body.args.foo2", "bar2", "check param foo2")
|
AssertEqual("body.args.foo2", "bar2", "check param foo2")
|
||||||
stepPOSTData = NewStep("post form data").
|
stepPOSTData = hrp.NewStep("post form data").
|
||||||
POST("/post").
|
POST("/post").
|
||||||
WithParams(map[string]interface{}{"foo1": "bar1", "foo2": "bar2"}).
|
WithParams(map[string]interface{}{"foo1": "bar1", "foo2": "bar2"}).
|
||||||
WithHeaders(map[string]string{"User-Agent": "HttpRunnerPlus", "Content-Type": "application/x-www-form-urlencoded"}).
|
WithHeaders(map[string]string{"User-Agent": "HttpRunnerPlus", "Content-Type": "application/x-www-form-urlencoded"}).
|
||||||
@@ -33,7 +31,7 @@ var (
|
|||||||
|
|
||||||
func TestRunRequestGetToStruct(t *testing.T) {
|
func TestRunRequestGetToStruct(t *testing.T) {
|
||||||
tStep := stepGET
|
tStep := stepGET
|
||||||
if tStep.Request.Method != httpGET {
|
if tStep.Request.Method != hrp.HTTP_GET {
|
||||||
t.Fatalf("tStep.Request.Method != GET")
|
t.Fatalf("tStep.Request.Method != GET")
|
||||||
}
|
}
|
||||||
if tStep.Request.URL != "/get" {
|
if tStep.Request.URL != "/get" {
|
||||||
@@ -48,7 +46,7 @@ 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")
|
||||||
}
|
}
|
||||||
validator, ok := tStep.Validators[0].(Validator)
|
validator, ok := tStep.Validators[0].(hrp.Validator)
|
||||||
if !ok || validator.Check != "status_code" || validator.Expect != 200 {
|
if !ok || validator.Check != "status_code" || validator.Expect != 200 {
|
||||||
t.Fatalf("tStep.Validators mismatch")
|
t.Fatalf("tStep.Validators mismatch")
|
||||||
}
|
}
|
||||||
@@ -56,7 +54,7 @@ func TestRunRequestGetToStruct(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunRequestPostDataToStruct(t *testing.T) {
|
func TestRunRequestPostDataToStruct(t *testing.T) {
|
||||||
tStep := stepPOSTData
|
tStep := stepPOSTData
|
||||||
if tStep.Request.Method != httpPOST {
|
if tStep.Request.Method != hrp.HTTP_POST {
|
||||||
t.Fatalf("tStep.Request.Method != POST")
|
t.Fatalf("tStep.Request.Method != POST")
|
||||||
}
|
}
|
||||||
if tStep.Request.URL != "/post" {
|
if tStep.Request.URL != "/post" {
|
||||||
@@ -74,18 +72,18 @@ 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")
|
||||||
}
|
}
|
||||||
validator, ok := tStep.Validators[0].(Validator)
|
validator, ok := tStep.Validators[0].(hrp.Validator)
|
||||||
if !ok || validator.Check != "status_code" || validator.Expect != 200 {
|
if !ok || validator.Check != "status_code" || validator.Expect != 200 {
|
||||||
t.Fatalf("tStep.Validators mismatch")
|
t.Fatalf("tStep.Validators mismatch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunRequestStatOn(t *testing.T) {
|
func TestRunRequestStatOn(t *testing.T) {
|
||||||
testcase := TestCase{
|
testcase := hrp.TestCase{
|
||||||
Config: NewConfig("test").SetBaseURL("https://postman-echo.com"),
|
Config: hrp.NewConfig("test").SetBaseURL("https://postman-echo.com"),
|
||||||
TestSteps: []IStep{stepGET, stepPOSTData},
|
TestSteps: []hrp.IStep{stepGET, stepPOSTData},
|
||||||
}
|
}
|
||||||
caseRunner, _ := NewRunner(t).SetHTTPStatOn().NewCaseRunner(testcase)
|
caseRunner, _ := hrp.NewRunner(t).SetHTTPStatOn().NewCaseRunner(testcase)
|
||||||
sessionRunner := caseRunner.NewSession()
|
sessionRunner := caseRunner.NewSession()
|
||||||
summary, err := sessionRunner.Start(nil)
|
summary, err := sessionRunner.Start(nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -162,15 +160,15 @@ func TestRunRequestStatOn(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRunCaseWithTimeout(t *testing.T) {
|
func TestRunCaseWithTimeout(t *testing.T) {
|
||||||
r := NewRunner(t)
|
r := hrp.NewRunner(t)
|
||||||
|
|
||||||
// global timeout
|
// global timeout
|
||||||
testcase1 := &TestCase{
|
testcase1 := &hrp.TestCase{
|
||||||
Config: NewConfig("TestCase1").
|
Config: hrp.NewConfig("TestCase1").
|
||||||
SetRequestTimeout(10). // set global timeout to 10s
|
SetRequestTimeout(10). // set global timeout to 10s
|
||||||
SetBaseURL("https://postman-echo.com"),
|
SetBaseURL("https://postman-echo.com"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("step1").
|
hrp.NewStep("step1").
|
||||||
GET("/delay/1").
|
GET("/delay/1").
|
||||||
Validate().
|
Validate().
|
||||||
AssertEqual("status_code", 200, "check status code"),
|
AssertEqual("status_code", 200, "check status code"),
|
||||||
@@ -181,12 +179,12 @@ func TestRunCaseWithTimeout(t *testing.T) {
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
testcase2 := &TestCase{
|
testcase2 := &hrp.TestCase{
|
||||||
Config: NewConfig("TestCase2").
|
Config: hrp.NewConfig("TestCase2").
|
||||||
SetRequestTimeout(5). // set global timeout to 10s
|
SetRequestTimeout(5). // set global timeout to 10s
|
||||||
SetBaseURL("https://postman-echo.com"),
|
SetBaseURL("https://postman-echo.com"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("step1").
|
hrp.NewStep("step1").
|
||||||
GET("/delay/10").
|
GET("/delay/10").
|
||||||
Validate().
|
Validate().
|
||||||
AssertEqual("status_code", 200, "check status code"),
|
AssertEqual("status_code", 200, "check status code"),
|
||||||
@@ -198,12 +196,12 @@ func TestRunCaseWithTimeout(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// step timeout
|
// step timeout
|
||||||
testcase3 := &TestCase{
|
testcase3 := &hrp.TestCase{
|
||||||
Config: NewConfig("TestCase3").
|
Config: hrp.NewConfig("TestCase3").
|
||||||
SetRequestTimeout(10).
|
SetRequestTimeout(10).
|
||||||
SetBaseURL("https://postman-echo.com"),
|
SetBaseURL("https://postman-echo.com"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("step2").
|
hrp.NewStep("step2").
|
||||||
GET("/delay/11").
|
GET("/delay/11").
|
||||||
SetTimeout(15*time.Second). // set step timeout to 4s
|
SetTimeout(15*time.Second). // set step timeout to 4s
|
||||||
Validate().
|
Validate().
|
||||||
@@ -215,70 +213,3 @@ func TestRunCaseWithTimeout(t *testing.T) {
|
|||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchJmespath(t *testing.T) {
|
|
||||||
testText := `{"a": {"b": "foo"}, "c": "bar", "d": {"e": [{"f": "foo"}, {"f": "bar"}]}}`
|
|
||||||
testData := []struct {
|
|
||||||
raw string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{"body.a.b", "foo"},
|
|
||||||
{"body.c", "bar"},
|
|
||||||
{"body.d.e[0].f", "foo"},
|
|
||||||
{"body.d.e[1].f", "bar"},
|
|
||||||
}
|
|
||||||
resp := http.Response{}
|
|
||||||
resp.Body = io.NopCloser(strings.NewReader(testText))
|
|
||||||
respObj, err := newHttpResponseObject(t, newParser(), &resp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
for _, data := range testData {
|
|
||||||
if !assert.Equal(t, data.expected, respObj.searchJmespath(data.raw)) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSearchRegexp(t *testing.T) {
|
|
||||||
testText := `
|
|
||||||
<ul class="nav navbar-nav navbar-right">
|
|
||||||
<li><a href="/order/addToCart" style="color: white"><i class="fa fa-shopping-cart fa-2x"></i><span class="badge">0</span></a></li>
|
|
||||||
<li class="dropdown">
|
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#" style="color: white">
|
|
||||||
Leo <i class="fa fa-cog fa-2x"></i><span class="caret"></span></a>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li><a href="/user/changePassword">Change Password</a></li>
|
|
||||||
<li><a href="/user/addAddress">Shipping</a></li>
|
|
||||||
<li><a href="/user/addCard">Payment</a></li>
|
|
||||||
<li><a href="/order/orderHistory">Order History</a></li>
|
|
||||||
<li><a href="/user/signOut">Sign Out</a></li>
|
|
||||||
</ul>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li> </li>
|
|
||||||
<li><a href="/user/signOut" style="color: white"><i class="fa fa-sign-out fa-2x"></i>
|
|
||||||
Sign Out</a></li>
|
|
||||||
</ul>
|
|
||||||
`
|
|
||||||
testData := []struct {
|
|
||||||
raw string
|
|
||||||
expected string
|
|
||||||
}{
|
|
||||||
{"/user/signOut\">(.*)</a></li>", "Sign Out"},
|
|
||||||
{"<li><a href=\"/user/(.*)\" style", "signOut"},
|
|
||||||
{" (.*) <i class=\"fa fa-cog fa-2x\"></i>", "Leo"},
|
|
||||||
}
|
|
||||||
// new response object
|
|
||||||
resp := http.Response{}
|
|
||||||
resp.Body = io.NopCloser(strings.NewReader(testText))
|
|
||||||
respObj, err := newHttpResponseObject(t, newParser(), &resp)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
for _, data := range testData {
|
|
||||||
if !assert.Equal(t, data.expected, respObj.searchRegexp(data.raw)) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +1,88 @@
|
|||||||
//go:build localtest
|
//go:build localtest
|
||||||
|
|
||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIOSSettingsAction(t *testing.T) {
|
func TestIOSSettingsAction(t *testing.T) {
|
||||||
testCase := &TestCase{
|
testCase := &hrp.TestCase{
|
||||||
Config: NewConfig("ios ui action on Settings").
|
Config: hrp.NewConfig("ios ui action on Settings").
|
||||||
SetIOS(option.WithWDAPort(8700), option.WithWDAMjpegPort(8800)),
|
SetIOS(option.WithWDAPort(8700), option.WithWDAMjpegPort(8800)),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("launch Settings").
|
hrp.NewStep("launch Settings").
|
||||||
IOS().Home().TapByOCR("设置").
|
IOS().Home().TapByOCR("设置").
|
||||||
Validate().
|
Validate().
|
||||||
AssertNameExists("飞行模式").
|
AssertNameExists("飞行模式").
|
||||||
AssertLabelExists("蓝牙").
|
AssertLabelExists("蓝牙").
|
||||||
AssertOCRExists("个人热点"),
|
AssertOCRExists("个人热点"),
|
||||||
NewStep("swipe up and down").
|
hrp.NewStep("swipe up and down").
|
||||||
IOS().SwipeUp().SwipeUp().SwipeDown(),
|
IOS().SwipeUp().SwipeUp().SwipeDown(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := NewRunner(t).Run(testCase)
|
err := hrp.NewRunner(t).Run(testCase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIOSSearchApp(t *testing.T) {
|
func TestIOSSearchApp(t *testing.T) {
|
||||||
testCase := &TestCase{
|
testCase := &hrp.TestCase{
|
||||||
Config: NewConfig("ios ui action on Search App 资源库"),
|
Config: hrp.NewConfig("ios ui action on Search App 资源库"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("进入 App 资源库 搜索框").
|
hrp.NewStep("进入 App 资源库 搜索框").
|
||||||
IOS().Home().SwipeLeft().SwipeLeft().TapByCV("dewey-search-field").
|
IOS().Home().SwipeLeft().SwipeLeft().TapByCV("dewey-search-field").
|
||||||
Validate().
|
Validate().
|
||||||
AssertLabelExists("取消"),
|
AssertLabelExists("取消"),
|
||||||
NewStep("搜索抖音").
|
hrp.NewStep("搜索抖音").
|
||||||
IOS().Input("抖音\n"),
|
IOS().Input("抖音\n"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := NewRunner(t).Run(testCase)
|
err := hrp.NewRunner(t).Run(testCase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIOSAppLaunch(t *testing.T) {
|
func TestIOSAppLaunch(t *testing.T) {
|
||||||
testCase := &TestCase{
|
testCase := &hrp.TestCase{
|
||||||
Config: NewConfig("启动 & 关闭 App").
|
Config: hrp.NewConfig("启动 & 关闭 App").
|
||||||
SetIOS(option.WithWDAPort(8700), option.WithWDAMjpegPort(8800)),
|
SetIOS(option.WithWDAPort(8700), option.WithWDAMjpegPort(8800)),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("终止今日头条").
|
hrp.NewStep("终止今日头条").
|
||||||
IOS().AppTerminate("com.ss.iphone.article.News"),
|
IOS().AppTerminate("com.ss.iphone.article.News"),
|
||||||
NewStep("启动今日头条").
|
hrp.NewStep("启动今日头条").
|
||||||
IOS().AppLaunch("com.ss.iphone.article.News"),
|
IOS().AppLaunch("com.ss.iphone.article.News"),
|
||||||
NewStep("终止今日头条").
|
hrp.NewStep("终止今日头条").
|
||||||
IOS().AppTerminate("com.ss.iphone.article.News"),
|
IOS().AppTerminate("com.ss.iphone.article.News"),
|
||||||
NewStep("启动今日头条").
|
hrp.NewStep("启动今日头条").
|
||||||
IOS().AppLaunch("com.ss.iphone.article.News"),
|
IOS().AppLaunch("com.ss.iphone.article.News"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := NewRunner(t).Run(testCase)
|
err := hrp.NewRunner(t).Run(testCase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAndroidAction(t *testing.T) {
|
func TestAndroidAction(t *testing.T) {
|
||||||
testCase := &TestCase{
|
testCase := &hrp.TestCase{
|
||||||
Config: NewConfig("android ui action"),
|
Config: hrp.NewConfig("android ui action"),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("launch douyin").
|
hrp.NewStep("launch douyin").
|
||||||
Android().Serial("xxx").TapByOCR("抖音").
|
Android().Serial("xxx").TapByOCR("抖音").
|
||||||
Validate().
|
Validate().
|
||||||
AssertNameExists("首页", "首页 tab 不存在").
|
AssertNameExists("首页", "首页 tab 不存在").
|
||||||
AssertNameExists("消息", "消息 tab 不存在"),
|
AssertNameExists("消息", "消息 tab 不存在"),
|
||||||
NewStep("swipe up and down").
|
hrp.NewStep("swipe up and down").
|
||||||
Android().Serial("xxx").SwipeUp().SwipeUp().SwipeDown(),
|
Android().Serial("xxx").SwipeUp().SwipeUp().SwipeDown(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err := NewRunner(t).Run(testCase)
|
err := hrp.NewRunner(t).Run(testCase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,25 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenHTMLReport(t *testing.T) {
|
func TestGenHTMLReport(t *testing.T) {
|
||||||
summary := NewSummary()
|
summary := hrp.NewSummary()
|
||||||
|
|
||||||
caseSummary1 := NewCaseSummary()
|
caseSummary1 := hrp.NewCaseSummary()
|
||||||
stepResult1 := &StepResult{}
|
stepResult1 := &hrp.StepResult{}
|
||||||
caseSummary1.AddStepResult(stepResult1)
|
caseSummary1.AddStepResult(stepResult1)
|
||||||
summary.AddCaseSummary(caseSummary1)
|
summary.AddCaseSummary(caseSummary1)
|
||||||
|
|
||||||
caseSummary2 := NewCaseSummary()
|
caseSummary2 := hrp.NewCaseSummary()
|
||||||
stepResult2 := &StepResult{
|
stepResult2 := &hrp.StepResult{
|
||||||
Name: "Test",
|
Name: "Test",
|
||||||
StepType: StepTypeRequest,
|
StepType: hrp.StepTypeRequest,
|
||||||
Success: false,
|
Success: false,
|
||||||
ContentSize: 0,
|
ContentSize: 0,
|
||||||
Attachments: "err",
|
Attachments: "err",
|
||||||
@@ -37,22 +39,22 @@ func TestGenHTMLReport(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTestCaseSummary_AddStepResult(t *testing.T) {
|
func TestTestCaseSummary_AddStepResult(t *testing.T) {
|
||||||
caseSummary := NewCaseSummary()
|
caseSummary := hrp.NewCaseSummary()
|
||||||
stepResult1 := &StepResult{
|
stepResult1 := &hrp.StepResult{
|
||||||
Name: "Test1",
|
Name: "Test1",
|
||||||
StepType: StepTypeRequest,
|
StepType: hrp.StepTypeRequest,
|
||||||
Success: true,
|
Success: true,
|
||||||
ContentSize: 0,
|
ContentSize: 0,
|
||||||
Attachments: "err",
|
Attachments: "err",
|
||||||
}
|
}
|
||||||
caseSummary.AddStepResult(stepResult1)
|
caseSummary.AddStepResult(stepResult1)
|
||||||
stepResult2 := &StepResult{
|
stepResult2 := &hrp.StepResult{
|
||||||
Name: "Test2",
|
Name: "Test2",
|
||||||
StepType: StepTypeTestCase,
|
StepType: hrp.StepTypeTestCase,
|
||||||
Success: false,
|
Success: false,
|
||||||
ContentSize: 0,
|
ContentSize: 0,
|
||||||
Attachments: "err",
|
Attachments: "err",
|
||||||
Data: []*StepResult{stepResult1},
|
Data: []*hrp.StepResult{stepResult1},
|
||||||
}
|
}
|
||||||
caseSummary.AddStepResult(stepResult2)
|
caseSummary.AddStepResult(stepResult2)
|
||||||
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
package hrp
|
package tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
hrp "github.com/httprunner/httprunner/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -25,10 +25,10 @@ var (
|
|||||||
demoAPIGETPath = tmpl("/api/get.yml")
|
demoAPIGETPath = tmpl("/api/get.yml")
|
||||||
)
|
)
|
||||||
|
|
||||||
var demoTestCaseWithThinkTimePath TestCasePath = hrpExamplesDir + "/think_time_test.json"
|
var demoTestCaseWithThinkTimePath hrp.TestCasePath = hrpExamplesDir + "/think_time_test.json"
|
||||||
|
|
||||||
var demoTestCaseWithPlugin = &TestCase{
|
var demoTestCaseWithPlugin = &hrp.TestCase{
|
||||||
Config: NewConfig("demo with complex mechanisms").
|
Config: hrp.NewConfig("demo with complex mechanisms").
|
||||||
SetBaseURL("https://postman-echo.com").
|
SetBaseURL("https://postman-echo.com").
|
||||||
WithVariables(map[string]interface{}{ // global level variables
|
WithVariables(map[string]interface{}{ // global level variables
|
||||||
"n": "${sum_ints(1, 2, 2)}",
|
"n": "${sum_ints(1, 2, 2)}",
|
||||||
@@ -37,9 +37,9 @@ var demoTestCaseWithPlugin = &TestCase{
|
|||||||
"varFoo1": "${gen_random_string($n)}",
|
"varFoo1": "${gen_random_string($n)}",
|
||||||
"varFoo2": "${max($a, $b)}", // 12.3; eval with built-in function
|
"varFoo2": "${max($a, $b)}", // 12.3; eval with built-in function
|
||||||
}),
|
}),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("transaction 1 start").StartTransaction("tran1"), // start transaction
|
hrp.NewStep("transaction 1 start").StartTransaction("tran1"), // start transaction
|
||||||
NewStep("get with params").
|
hrp.NewStep("get with params").
|
||||||
WithVariables(map[string]interface{}{ // step level variables
|
WithVariables(map[string]interface{}{ // step level variables
|
||||||
"n": 3, // inherit config level variables if not set in step level, a/varFoo1
|
"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
|
"b": 34.5, // override config level variable if existed, n/b/varFoo2
|
||||||
@@ -59,8 +59,8 @@ var demoTestCaseWithPlugin = &TestCase{
|
|||||||
AssertLengthEqual("body.args.foo1", 5, "check args foo1"). // validate response body with jmespath
|
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
|
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
|
AssertEqual("body.args.foo2", "34.5", "check args foo2"), // notice: request params value will be converted to string
|
||||||
NewStep("transaction 1 end").EndTransaction("tran1"), // end transaction
|
hrp.NewStep("transaction 1 end").EndTransaction("tran1"), // end transaction
|
||||||
NewStep("post json data").
|
hrp.NewStep("post json data").
|
||||||
POST("/post").
|
POST("/post").
|
||||||
WithBody(map[string]interface{}{
|
WithBody(map[string]interface{}{
|
||||||
"foo1": "$varFoo1", // reference former extracted variable
|
"foo1": "$varFoo1", // reference former extracted variable
|
||||||
@@ -70,7 +70,7 @@ var demoTestCaseWithPlugin = &TestCase{
|
|||||||
AssertEqual("status_code", 200, "check status code").
|
AssertEqual("status_code", 200, "check status code").
|
||||||
AssertLengthEqual("body.json.foo1", 5, "check args foo1").
|
AssertLengthEqual("body.json.foo1", 5, "check args foo1").
|
||||||
AssertEqual("body.json.foo2", 12.3, "check args foo2"),
|
AssertEqual("body.json.foo2", 12.3, "check args foo2"),
|
||||||
NewStep("post form data").
|
hrp.NewStep("post form data").
|
||||||
POST("/post").
|
POST("/post").
|
||||||
WithHeaders(map[string]string{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}).
|
WithHeaders(map[string]string{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}).
|
||||||
WithBody(map[string]interface{}{
|
WithBody(map[string]interface{}{
|
||||||
@@ -84,15 +84,15 @@ var demoTestCaseWithPlugin = &TestCase{
|
|||||||
AssertEqual("status_code", 200, "check status code").
|
AssertEqual("status_code", 200, "check status code").
|
||||||
AssertLengthEqual("body.form.foo1", 5, "check args foo1").
|
AssertLengthEqual("body.form.foo1", 5, "check args foo1").
|
||||||
AssertEqual("body.form.foo2", "12.3", "check args foo2"), // form data will be converted to string
|
AssertEqual("body.form.foo2", "12.3", "check args foo2"), // form data will be converted to string
|
||||||
NewStep("get with timestamp").
|
hrp.NewStep("get with timestamp").
|
||||||
GET("/get").WithParams(map[string]interface{}{"time": "$varTime"}).
|
GET("/get").WithParams(map[string]interface{}{"time": "$varTime"}).
|
||||||
Validate().
|
Validate().
|
||||||
AssertLengthEqual("body.args.time", 13, "check extracted var timestamp"),
|
AssertLengthEqual("body.args.time", 13, "check extracted var timestamp"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var demoTestCaseWithoutPlugin = &TestCase{
|
var demoTestCaseWithoutPlugin = &hrp.TestCase{
|
||||||
Config: NewConfig("demo without custom function plugin").
|
Config: hrp.NewConfig("demo without custom function plugin").
|
||||||
SetBaseURL("https://postman-echo.com").
|
SetBaseURL("https://postman-echo.com").
|
||||||
WithVariables(map[string]interface{}{ // global level variables
|
WithVariables(map[string]interface{}{ // global level variables
|
||||||
"n": 5,
|
"n": 5,
|
||||||
@@ -101,9 +101,9 @@ var demoTestCaseWithoutPlugin = &TestCase{
|
|||||||
"varFoo1": "${gen_random_string($n)}",
|
"varFoo1": "${gen_random_string($n)}",
|
||||||
"varFoo2": "${max($a, $b)}", // 12.3; eval with built-in function
|
"varFoo2": "${max($a, $b)}", // 12.3; eval with built-in function
|
||||||
}),
|
}),
|
||||||
TestSteps: []IStep{
|
TestSteps: []hrp.IStep{
|
||||||
NewStep("transaction 1 start").StartTransaction("tran1"), // start transaction
|
hrp.NewStep("transaction 1 start").StartTransaction("tran1"), // start transaction
|
||||||
NewStep("get with params").
|
hrp.NewStep("get with params").
|
||||||
WithVariables(map[string]interface{}{ // step level variables
|
WithVariables(map[string]interface{}{ // step level variables
|
||||||
"n": 3, // inherit config level variables if not set in step level, a/varFoo1
|
"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
|
"b": 34.5, // override config level variable if existed, n/b/varFoo2
|
||||||
@@ -121,8 +121,8 @@ var demoTestCaseWithoutPlugin = &TestCase{
|
|||||||
AssertLengthEqual("body.args.foo1", 5, "check args foo1"). // validate response body with jmespath
|
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
|
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
|
AssertEqual("body.args.foo2", "34.5", "check args foo2"), // notice: request params value will be converted to string
|
||||||
NewStep("transaction 1 end").EndTransaction("tran1"), // end transaction
|
hrp.NewStep("transaction 1 end").EndTransaction("tran1"), // end transaction
|
||||||
NewStep("post json data").
|
hrp.NewStep("post json data").
|
||||||
POST("/post").
|
POST("/post").
|
||||||
WithBody(map[string]interface{}{
|
WithBody(map[string]interface{}{
|
||||||
"foo1": "$varFoo1", // reference former extracted variable
|
"foo1": "$varFoo1", // reference former extracted variable
|
||||||
@@ -132,7 +132,7 @@ var demoTestCaseWithoutPlugin = &TestCase{
|
|||||||
AssertEqual("status_code", 200, "check status code").
|
AssertEqual("status_code", 200, "check status code").
|
||||||
AssertLengthEqual("body.json.foo1", 5, "check args foo1").
|
AssertLengthEqual("body.json.foo1", 5, "check args foo1").
|
||||||
AssertEqual("body.json.foo2", 12.3, "check args foo2"),
|
AssertEqual("body.json.foo2", 12.3, "check args foo2"),
|
||||||
NewStep("post form data").
|
hrp.NewStep("post form data").
|
||||||
POST("/post").
|
POST("/post").
|
||||||
WithHeaders(map[string]string{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}).
|
WithHeaders(map[string]string{"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}).
|
||||||
WithBody(map[string]interface{}{
|
WithBody(map[string]interface{}{
|
||||||
@@ -146,7 +146,7 @@ var demoTestCaseWithoutPlugin = &TestCase{
|
|||||||
AssertEqual("status_code", 200, "check status code").
|
AssertEqual("status_code", 200, "check status code").
|
||||||
AssertLengthEqual("body.form.foo1", 5, "check args foo1").
|
AssertLengthEqual("body.form.foo1", 5, "check args foo1").
|
||||||
AssertEqual("body.form.foo2", "12.3", "check args foo2"), // form data will be converted to string
|
AssertEqual("body.form.foo2", "12.3", "check args foo2"), // form data will be converted to string
|
||||||
NewStep("get with timestamp").
|
hrp.NewStep("get with timestamp").
|
||||||
GET("/get").WithParams(map[string]interface{}{"time": "$varTime"}).
|
GET("/get").WithParams(map[string]interface{}{"time": "$varTime"}).
|
||||||
Validate().
|
Validate().
|
||||||
AssertLengthEqual("body.args.time", 13, "check extracted var timestamp"),
|
AssertLengthEqual("body.args.time", 13, "check extracted var timestamp"),
|
||||||
@@ -172,29 +172,3 @@ func TestGenDemoTestCase(t *testing.T) {
|
|||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertCheckExpr(t *testing.T) {
|
|
||||||
exprs := []struct {
|
|
||||||
before string
|
|
||||||
after string
|
|
||||||
}{
|
|
||||||
// normal check expression
|
|
||||||
{"a.b.c", "a.b.c"},
|
|
||||||
{"a.\"b-c\".d", "a.\"b-c\".d"},
|
|
||||||
{"a.b-c.d", "a.b-c.d"},
|
|
||||||
{"body.args.a[-1]", "body.args.a[-1]"},
|
|
||||||
// check expression using regex
|
|
||||||
{"covering (.*) testing,", "covering (.*) testing,"},
|
|
||||||
{" (.*) a-b-c", " (.*) a-b-c"},
|
|
||||||
// abnormal check expression
|
|
||||||
{"headers.Content-Type", "headers.\"Content-Type\""},
|
|
||||||
{"headers.\"Content-Type", "headers.\"Content-Type\""},
|
|
||||||
{"headers.Content-Type\"", "headers.\"Content-Type\""},
|
|
||||||
{"headers.User-Agent", "headers.\"User-Agent\""},
|
|
||||||
}
|
|
||||||
for _, expr := range exprs {
|
|
||||||
if !assert.Equal(t, expr.after, convertJmespathExpr(expr.before)) {
|
|
||||||
t.Fatal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user