mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
feat: extract variables
This commit is contained in:
@@ -43,7 +43,7 @@ func (b *Boomer) convertBoomerTask(testcase *TestCase) *boomer.Task {
|
||||
config := &testcase.Config
|
||||
for _, step := range testcase.TestSteps {
|
||||
start := time.Now()
|
||||
err := runner.runStep(step, config)
|
||||
_, err := runner.runStep(step, config)
|
||||
elapsed := time.Since(start).Nanoseconds() / int64(time.Millisecond)
|
||||
|
||||
if err == nil {
|
||||
|
||||
@@ -5,18 +5,18 @@ import (
|
||||
)
|
||||
|
||||
func TestHttpBoomer(t *testing.T) {
|
||||
testcase1 := &TestCase{
|
||||
Config: TConfig{
|
||||
Name: "TestCase1",
|
||||
Weight: 2,
|
||||
},
|
||||
}
|
||||
testcase2 := &TestCase{
|
||||
Config: TConfig{
|
||||
Name: "TestCase2",
|
||||
Weight: 3,
|
||||
},
|
||||
}
|
||||
// testcase1 := &TestCase{
|
||||
// Config: TConfig{
|
||||
// Name: "TestCase1",
|
||||
// Weight: 2,
|
||||
// },
|
||||
// }
|
||||
// testcase2 := &TestCase{
|
||||
// Config: TConfig{
|
||||
// Name: "TestCase2",
|
||||
// Weight: 3,
|
||||
// },
|
||||
// }
|
||||
|
||||
Run(testcase1, testcase2)
|
||||
// Run(testcase1, testcase2)
|
||||
}
|
||||
|
||||
@@ -67,3 +67,9 @@ type TestCase struct {
|
||||
}
|
||||
|
||||
type TestCaseSummary struct{}
|
||||
|
||||
type StepData struct {
|
||||
Name string // step name
|
||||
Success bool // step execution result
|
||||
ExportVars map[string]interface{} // extract variables
|
||||
}
|
||||
|
||||
14
response.go
14
response.go
@@ -80,6 +80,20 @@ type ResponseObject struct {
|
||||
validationResults map[string]interface{}
|
||||
}
|
||||
|
||||
func (v *ResponseObject) Extract(extractors map[string]string) map[string]interface{} {
|
||||
if extractors == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
extractMapping := make(map[string]interface{})
|
||||
for key, value := range extractors {
|
||||
extractMapping[key] = v.searchJmespath(value)
|
||||
}
|
||||
|
||||
log.Printf("[Extract] extractMapping: %v", extractMapping)
|
||||
return extractMapping
|
||||
}
|
||||
|
||||
func (v *ResponseObject) Validate(validators []TValidator, variablesMapping map[string]interface{}) error {
|
||||
for _, validator := range validators {
|
||||
// parse check value
|
||||
|
||||
58
runner.go
58
runner.go
@@ -49,39 +49,56 @@ func (r *Runner) runCase(testcase *TestCase) error {
|
||||
config := &testcase.Config
|
||||
log.Printf("Start to run testcase: %v", config.Name)
|
||||
|
||||
extractedVariables := make(map[string]interface{})
|
||||
|
||||
for _, step := range testcase.TestSteps {
|
||||
// override variables
|
||||
// step variables > extracted variables from previous steps
|
||||
step.ToStruct().Variables = mergeVariables(step.ToStruct().Variables, extractedVariables)
|
||||
// step variables > testcase config variables
|
||||
step.ToStruct().Variables = mergeVariables(step.ToStruct().Variables, config.Variables)
|
||||
|
||||
r.runStep(step, config)
|
||||
stepData, err := r.runStep(step, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// update extracted variables
|
||||
for k, v := range stepData.ExportVars {
|
||||
extractedVariables[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runner) runStep(step IStep, config *TConfig) error {
|
||||
func (r *Runner) runStep(step IStep, config *TConfig) (stepData *StepData, err error) {
|
||||
log.Printf("run step begin: %v >>>>>>", step.Name())
|
||||
if tc, ok := step.(*testcaseWithOptionalArgs); ok {
|
||||
// run referenced testcase
|
||||
log.Printf("run referenced testcase: %v", tc.step.Name)
|
||||
// TODO: override testcase config
|
||||
if err := r.runStepTestCase(tc.step); err != nil {
|
||||
return err
|
||||
stepData, err = r.runStepTestCase(tc.step)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// run request
|
||||
tStep := parseStep(step, config)
|
||||
if err := r.runStepRequest(tStep); err != nil {
|
||||
return err
|
||||
stepData, err = r.runStepRequest(tStep)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Printf("run step end: %v <<<<<<\n", step.Name())
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runner) runStepRequest(step *TStep) error {
|
||||
func (r *Runner) runStepRequest(step *TStep) (stepData *StepData, err error) {
|
||||
stepData = &StepData{
|
||||
Name: step.Name,
|
||||
Success: false,
|
||||
}
|
||||
|
||||
// prepare request args
|
||||
var v []interface{}
|
||||
if len(step.Request.Headers) > 0 {
|
||||
@@ -111,23 +128,36 @@ func (r *Runner) runStepRequest(step *TStep) error {
|
||||
req.Debug = r.debug
|
||||
resp, err := r.Client.Do(string(step.Request.Method), step.Request.URL, v...)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
defer resp.Response().Body.Close()
|
||||
|
||||
// validate response
|
||||
// new response object
|
||||
respObj := NewResponseObject(r.t, resp)
|
||||
|
||||
// extract variables from response
|
||||
extractors := step.Extract
|
||||
extractMapping := respObj.Extract(extractors)
|
||||
stepData.ExportVars = extractMapping
|
||||
|
||||
// validate response
|
||||
err = respObj.Validate(step.Validators, step.Variables)
|
||||
if err != nil {
|
||||
return err
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
stepData.Success = true
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runner) runStepTestCase(step *TStep) error {
|
||||
func (r *Runner) runStepTestCase(step *TStep) (stepData *StepData, err error) {
|
||||
stepData = &StepData{
|
||||
Name: step.Name,
|
||||
Success: false,
|
||||
}
|
||||
testcase := step.TestCase
|
||||
return r.runCase(testcase)
|
||||
err = r.runCase(testcase)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runner) GetSummary() *TestCaseSummary {
|
||||
|
||||
@@ -78,10 +78,10 @@ func TestRunRequestRun(t *testing.T) {
|
||||
BaseURL: "https://postman-echo.com",
|
||||
}
|
||||
runner := NewRunner().SetDebug(true).WithTestingT(t)
|
||||
if err := runner.runStep(stepGET, config); err != nil {
|
||||
if _, err := runner.runStep(stepGET, config); err != nil {
|
||||
t.Fatalf("tStep.Run() error: %s", err)
|
||||
}
|
||||
if err := runner.runStep(stepPOSTData, config); err != nil {
|
||||
if _, err := runner.runStep(stepPOSTData, config); err != nil {
|
||||
t.Fatalf("tStepPOSTData.Run() error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user