mirror of
https://github.com/httprunner/httprunner.git
synced 2026-07-08 22:13:13 +08:00
Merge pull request #104 from xucong053/main
feat: support text/html extraction with regex
This commit is contained in:
42
response.go
42
response.go
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -85,6 +86,18 @@ type responseObject struct {
|
|||||||
validationResults []*validationResult
|
validationResults []*validationResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const textExtractorSubRegexp string = `(.*)`
|
||||||
|
|
||||||
|
func (v *responseObject) extractField(value string) interface{} {
|
||||||
|
var result interface{}
|
||||||
|
if strings.Contains(value, textExtractorSubRegexp) {
|
||||||
|
result = v.searchRegexp(value)
|
||||||
|
} else {
|
||||||
|
result = v.searchJmespath(value)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func (v *responseObject) Extract(extractors map[string]string) map[string]interface{} {
|
func (v *responseObject) Extract(extractors map[string]string) map[string]interface{} {
|
||||||
if extractors == nil {
|
if extractors == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -92,7 +105,7 @@ func (v *responseObject) Extract(extractors map[string]string) map[string]interf
|
|||||||
|
|
||||||
extractMapping := make(map[string]interface{})
|
extractMapping := make(map[string]interface{})
|
||||||
for key, value := range extractors {
|
for key, value := range extractors {
|
||||||
extractedValue := v.searchJmespath(value)
|
extractedValue := v.extractField(value)
|
||||||
log.Info().Str("from", value).Interface("value", extractedValue).Msg("extract value")
|
log.Info().Str("from", value).Interface("value", extractedValue).Msg("extract value")
|
||||||
log.Info().Str("variable", key).Interface("value", extractedValue).Msg("set variable")
|
log.Info().Str("variable", key).Interface("value", extractedValue).Msg("set variable")
|
||||||
extractMapping[key] = extractedValue
|
extractMapping[key] = extractedValue
|
||||||
@@ -113,7 +126,8 @@ func (v *responseObject) Validate(validators []Validator, variablesMapping map[s
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
checkValue = v.searchJmespath(checkItem)
|
// regExp or jmesPath
|
||||||
|
checkValue = v.extractField(checkItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get assert method
|
// get assert method
|
||||||
@@ -179,3 +193,27 @@ func (v *responseObject) searchJmespath(expr string) interface{} {
|
|||||||
}
|
}
|
||||||
return checkValue
|
return checkValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *responseObject) searchRegexp(expr string) interface{} {
|
||||||
|
respMap, ok := v.respObjMeta.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
log.Error().Interface("resp", v.respObjMeta).Msg("convert respObjMeta to map failed")
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
bodyStr, ok := respMap["body"].(string)
|
||||||
|
if !ok {
|
||||||
|
log.Error().Interface("resp", respMap).Msg("convert body to string failed")
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
regexpCompile, err := regexp.Compile(expr)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Str("expr", expr).Err(err).Msg("compile expr failed")
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
match := regexpCompile.FindStringSubmatch(bodyStr)
|
||||||
|
if match != nil || len(match) > 1 {
|
||||||
|
return match[1] //return first matched result in parentheses
|
||||||
|
}
|
||||||
|
log.Error().Str("expr", expr).Msg("search regexp failed")
|
||||||
|
return expr
|
||||||
|
}
|
||||||
|
|||||||
35
response_test.go
Normal file
35
response_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package hrp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSearchRegexp(t *testing.T) {
|
||||||
|
testText := `hrp aims to be a one-stop solution for HTTP(S) testing, covering API testing, load testing and digital experience monitoring (DEM).`
|
||||||
|
testData := []struct {
|
||||||
|
raw string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"covering (.*) testing,", "API"},
|
||||||
|
{" (.*) to", "aims"},
|
||||||
|
{"^(.*) aims", "hrp"},
|
||||||
|
{".* (.*?)$", "(DEM)."},
|
||||||
|
}
|
||||||
|
// new response object
|
||||||
|
resp := http.Response{}
|
||||||
|
resp.Body = io.NopCloser(strings.NewReader(testText))
|
||||||
|
respObj, err := newResponseObject(t, newParser(), &resp)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
for _, data := range testData {
|
||||||
|
if !assert.Equal(t, data.expected, respObj.searchRegexp(data.raw)) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user