mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-13 05:20:06 +08:00
feat: data-driven.
This commit is contained in:
@@ -45,8 +45,13 @@ func (b *hrpBoomer) Run(testcases ...ITestCase) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
task := b.convertBoomerTask(testcase)
|
||||
taskSlice = append(taskSlice, task)
|
||||
cfg := testcase.Config.ToStruct()
|
||||
parameters := getParameters(testcase.Config)
|
||||
for _, parameter := range parameters {
|
||||
cfg.Variables = mergeVariables(parameter, cfg.Variables)
|
||||
task := b.convertBoomerTask(testcase)
|
||||
taskSlice = append(taskSlice, task)
|
||||
}
|
||||
}
|
||||
b.Boomer.Run(taskSlice...)
|
||||
}
|
||||
|
||||
15
models.go
15
models.go
@@ -13,13 +13,14 @@ const (
|
||||
// TConfig represents config data structure for testcase.
|
||||
// Each testcase should contain one config part.
|
||||
type TConfig struct {
|
||||
Name string `json:"name" yaml:"name"` // required
|
||||
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
||||
BaseURL string `json:"base_url,omitempty" yaml:"base_url,omitempty"`
|
||||
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
Parameters map[string]interface{} `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Export []string `json:"export,omitempty" yaml:"export,omitempty"`
|
||||
Weight int `json:"weight,omitempty" yaml:"weight,omitempty"`
|
||||
Name string `json:"name" yaml:"name"` // required
|
||||
Verify bool `json:"verify,omitempty" yaml:"verify,omitempty"`
|
||||
BaseURL string `json:"base_url,omitempty" yaml:"base_url,omitempty"`
|
||||
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
Parameters map[string]interface{} `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
ParametersSetting map[string]interface{} `json:"parameters_setting,omitempty" yaml:"parameters_setting,omitempty"`
|
||||
Export []string `json:"export,omitempty" yaml:"export,omitempty"`
|
||||
Weight int `json:"weight,omitempty" yaml:"weight,omitempty"`
|
||||
}
|
||||
|
||||
// Request represents HTTP request data structure.
|
||||
|
||||
32
parser.go
32
parser.go
@@ -3,10 +3,12 @@ package hrp
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/maja42/goval"
|
||||
"github.com/pkg/errors"
|
||||
@@ -515,18 +517,44 @@ func findallVariables(raw string) variableSet {
|
||||
return varSet
|
||||
}
|
||||
|
||||
func shuffleCartesianProduct(slice []map[string]interface{}) {
|
||||
r := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
for len(slice) > 0 {
|
||||
n := len(slice)
|
||||
randIndex := r.Intn(n)
|
||||
slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1]
|
||||
slice = slice[:n-1]
|
||||
}
|
||||
}
|
||||
|
||||
func genCartesianProduct(params [][]map[string]interface{}) []map[string]interface{} {
|
||||
var cartesianProduct []map[string]interface{}
|
||||
cartesianProduct = params[0]
|
||||
for i := 0; i < len(params)-1; i++ {
|
||||
for _, param1 := range params[i] {
|
||||
var tempProduct []map[string]interface{}
|
||||
for _, param1 := range cartesianProduct {
|
||||
for _, param2 := range params[i+1] {
|
||||
cartesianProduct = append(cartesianProduct, mergeVariables(param1, param2))
|
||||
tempProduct = append(tempProduct, mergeVariables(param1, param2))
|
||||
}
|
||||
}
|
||||
cartesianProduct = tempProduct
|
||||
}
|
||||
return cartesianProduct
|
||||
}
|
||||
|
||||
func getParameters(config IConfig) []map[string]interface{} {
|
||||
cfg := config.ToStruct()
|
||||
// parse config parameters
|
||||
parsedParams, err := parseParameters(cfg.Parameters, cfg.Variables)
|
||||
if err != nil {
|
||||
log.Error().Interface("params", cfg.Parameters).Err(err).Msg("parse config parameters failed")
|
||||
}
|
||||
if cfg.ParametersSetting["strategy"] != nil && strings.ToLower(cfg.ParametersSetting["strategy"].(string)) == "random" {
|
||||
shuffleCartesianProduct(parsedParams)
|
||||
}
|
||||
return parsedParams
|
||||
}
|
||||
|
||||
func parseParameters(parameters map[string]interface{}, variablesMapping map[string]interface{}) ([]map[string]interface{}, error) {
|
||||
var parsedParametersList [][]map[string]interface{}
|
||||
for k, v := range parameters {
|
||||
|
||||
13
runner.go
13
runner.go
@@ -128,16 +128,11 @@ func (r *hrpRunner) runCase(testcase *TestCase) error {
|
||||
if err := r.parseConfig(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfg := config.ToStruct()
|
||||
log.Info().Str("testcase", config.Name()).Msg("run testcase start")
|
||||
// parse config parameters
|
||||
parsedParams, err := parseParameters(config.ToStruct().Parameters, config.ToStruct().Variables)
|
||||
if err != nil {
|
||||
log.Error().Interface("params", config.ToStruct().Parameters).Err(err).Msg("parse config parameters failed")
|
||||
return err
|
||||
}
|
||||
for _, parameter := range parsedParams {
|
||||
config.ToStruct().Variables = mergeVariables(parameter, config.ToStruct().Variables)
|
||||
parameters := getParameters(config)
|
||||
for _, parameter := range parameters {
|
||||
cfg.Variables = mergeVariables(parameter, cfg.Variables)
|
||||
r.startTime = time.Now()
|
||||
for _, step := range testcase.TestSteps {
|
||||
_, err := r.runStep(step, config)
|
||||
|
||||
Reference in New Issue
Block a user