mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-07 08:27:35 +08:00
refactor: update summary in controller
This commit is contained in:
@@ -6,8 +6,8 @@ import (
|
|||||||
|
|
||||||
// general: [0, 20)
|
// general: [0, 20)
|
||||||
const (
|
const (
|
||||||
SUCCESS = 0
|
Success = 0
|
||||||
FAIL = 1
|
GeneralFail = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// loader: [20, 40)
|
// loader: [20, 40)
|
||||||
@@ -64,7 +64,7 @@ var errorsMap = map[error]int{
|
|||||||
|
|
||||||
func GetErrorCode(err error) int {
|
func GetErrorCode(err error) int {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return SUCCESS
|
return Success
|
||||||
}
|
}
|
||||||
|
|
||||||
e := errors.Cause(err)
|
e := errors.Cause(err)
|
||||||
@@ -72,5 +72,5 @@ func GetErrorCode(err error) int {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
return FAIL
|
return GeneralFail
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package hrp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LoadTestCases(iTestCases ...ITestCase) ([]*TestCase, error) {
|
||||||
|
testCases := make([]*TestCase, 0)
|
||||||
|
|
||||||
|
for _, iTestCase := range iTestCases {
|
||||||
|
if _, ok := iTestCase.(*TestCase); ok {
|
||||||
|
testcase, err := iTestCase.ToTestCase()
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("failed to convert ITestCase interface to TestCase struct")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
testCases = append(testCases, testcase)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// iTestCase should be a TestCasePath, file path or folder path
|
||||||
|
tcPath, ok := iTestCase.(*TestCasePath)
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("invalid iTestCase type")
|
||||||
|
}
|
||||||
|
|
||||||
|
casePath := tcPath.GetPath()
|
||||||
|
err := fs.WalkDir(os.DirFS(casePath), ".", func(path string, dir fs.DirEntry, e error) error {
|
||||||
|
if dir == nil {
|
||||||
|
// casePath is a file other than a dir
|
||||||
|
path = casePath
|
||||||
|
} else if dir.IsDir() && path != "." && strings.HasPrefix(path, ".") {
|
||||||
|
// skip hidden folders
|
||||||
|
return fs.SkipDir
|
||||||
|
} else {
|
||||||
|
// casePath is a dir
|
||||||
|
path = filepath.Join(casePath, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore non-testcase files
|
||||||
|
ext := filepath.Ext(path)
|
||||||
|
if ext != ".yml" && ext != ".yaml" && ext != ".json" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// filtered testcases
|
||||||
|
testCasePath := TestCasePath(path)
|
||||||
|
tc, err := testCasePath.ToTestCase()
|
||||||
|
if err != nil {
|
||||||
|
log.Warn().Err(err).Str("path", path).Msg("load testcase failed")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
testCases = append(testCases, tc)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "read dir failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Int("count", len(testCases)).Msg("load testcases successfully")
|
||||||
|
return testCases, nil
|
||||||
|
}
|
||||||
+3
-3
@@ -190,7 +190,7 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{}
|
|||||||
return raw, err
|
return raw, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := p.CallFunc(funcName, parsedArgs.([]interface{})...)
|
result, err := p.callFunc(funcName, parsedArgs.([]interface{})...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Str("funcName", funcName).Interface("arguments", arguments).
|
log.Error().Str("funcName", funcName).Interface("arguments", arguments).
|
||||||
Err(err).Msg("call function failed")
|
Err(err).Msg("call function failed")
|
||||||
@@ -251,9 +251,9 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{}
|
|||||||
return parsedString, nil
|
return parsedString, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallFunc calls function with arguments
|
// callFunc calls function with arguments
|
||||||
// only support return at most one result value
|
// only support return at most one result value
|
||||||
func (p *Parser) CallFunc(funcName string, arguments ...interface{}) (interface{}, error) {
|
func (p *Parser) callFunc(funcName string, arguments ...interface{}) (interface{}, error) {
|
||||||
// call with plugin function
|
// call with plugin function
|
||||||
if p.plugin != nil {
|
if p.plugin != nil {
|
||||||
if p.plugin.Has(funcName) {
|
if p.plugin.Has(funcName) {
|
||||||
|
|||||||
+4
-4
@@ -478,14 +478,14 @@ 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")
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|
||||||
// call function with one argument
|
// call function with one argument
|
||||||
timeStart := time.Now()
|
timeStart := time.Now()
|
||||||
_, err = parser.CallFunc("sleep", 1)
|
_, err = parser.callFunc("sleep", 1)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -494,7 +494,7 @@ func TestCallBuiltinFunction(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// call function with one argument
|
// call function with one argument
|
||||||
result, err := parser.CallFunc("gen_random_string", 10)
|
result, err := parser.callFunc("gen_random_string", 10)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@@ -503,7 +503,7 @@ func TestCallBuiltinFunction(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// call function with two argument
|
// call function with two argument
|
||||||
result, err = parser.CallFunc("max", float64(10), 9.99)
|
result, err = parser.callFunc("max", float64(10), 9.99)
|
||||||
if !assert.NoError(t, err) {
|
if !assert.NoError(t, err) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -317,9 +317,10 @@ func (r *HRPRunner) newCaseRunner(testcase *TestCase) (*testCaseRunner, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type testCaseRunner struct {
|
type testCaseRunner struct {
|
||||||
testCase *TestCase
|
testCase *TestCase
|
||||||
hrpRunner *HRPRunner
|
hrpRunner *HRPRunner
|
||||||
parser *Parser
|
parser *Parser
|
||||||
|
|
||||||
parsedConfig *TConfig
|
parsedConfig *TConfig
|
||||||
parametersIterator *ParametersIterator
|
parametersIterator *ParametersIterator
|
||||||
rootDir string // project root dir
|
rootDir string // project root dir
|
||||||
|
|||||||
+21
-19
@@ -35,14 +35,6 @@ func (r *SessionRunner) resetSession() {
|
|||||||
r.closeResponseChan = make(chan *wsCloseRespObject, 1)
|
r.closeResponseChan = make(chan *wsCloseRespObject, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SessionRunner) GetParser() *Parser {
|
|
||||||
return r.parser
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *SessionRunner) GetConfig() *TConfig {
|
|
||||||
return r.parsedConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *SessionRunner) HTTPStatOn() bool {
|
func (r *SessionRunner) HTTPStatOn() bool {
|
||||||
return r.hrpRunner.httpStatOn
|
return r.hrpRunner.httpStatOn
|
||||||
}
|
}
|
||||||
@@ -74,31 +66,41 @@ func (r *SessionRunner) Start(givenVars map[string]interface{}) error {
|
|||||||
log.Info().Str("step", stepName).
|
log.Info().Str("step", stepName).
|
||||||
Str("type", string(step.Type())).Msg("run step start")
|
Str("type", string(step.Type())).Msg("run step start")
|
||||||
|
|
||||||
|
// run step
|
||||||
stepResult, err := step.Run(r)
|
stepResult, err := step.Run(r)
|
||||||
stepResult.Name = stepName
|
stepResult.Name = stepName
|
||||||
if err != nil {
|
|
||||||
|
// update summary
|
||||||
|
r.summary.Records = append(r.summary.Records, stepResult)
|
||||||
|
r.summary.Stat.Total += 1
|
||||||
|
if stepResult.Success {
|
||||||
|
r.summary.Stat.Successes += 1
|
||||||
|
log.Info().
|
||||||
|
Str("step", stepResult.Name).
|
||||||
|
Str("type", string(stepResult.StepType)).
|
||||||
|
Bool("success", true).
|
||||||
|
Interface("exportVars", stepResult.ExportVars).
|
||||||
|
Msg("run step end")
|
||||||
|
} else {
|
||||||
|
r.summary.Stat.Failures += 1
|
||||||
|
// update summary result to failed
|
||||||
|
r.summary.Success = false
|
||||||
log.Error().
|
log.Error().
|
||||||
Str("step", stepResult.Name).
|
Str("step", stepResult.Name).
|
||||||
Str("type", string(stepResult.StepType)).
|
Str("type", string(stepResult.StepType)).
|
||||||
Bool("success", false).
|
Bool("success", false).
|
||||||
Msg("run step end")
|
Msg("run step end")
|
||||||
|
}
|
||||||
|
|
||||||
if r.hrpRunner.failfast {
|
// check if failfast
|
||||||
return errors.Wrap(err, "abort running due to failfast setting")
|
if err != nil && r.hrpRunner.failfast {
|
||||||
}
|
return errors.Wrap(err, "abort running due to failfast setting")
|
||||||
}
|
}
|
||||||
|
|
||||||
// update extracted variables
|
// update extracted variables
|
||||||
for k, v := range stepResult.ExportVars {
|
for k, v := range stepResult.ExportVars {
|
||||||
r.sessionVariables[k] = v
|
r.sessionVariables[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().
|
|
||||||
Str("step", stepResult.Name).
|
|
||||||
Str("type", string(stepResult.StepType)).
|
|
||||||
Bool("success", stepResult.Success).
|
|
||||||
Interface("exportVars", stepResult.ExportVars).
|
|
||||||
Msg("run step end")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// close websocket connection after all steps done
|
// close websocket connection after all steps done
|
||||||
|
|||||||
@@ -100,9 +100,6 @@ func (s *StepAPIWithOptionalArgs) Struct() *TStep {
|
|||||||
|
|
||||||
func (s *StepAPIWithOptionalArgs) Run(r *SessionRunner) (stepResult *StepResult, err error) {
|
func (s *StepAPIWithOptionalArgs) Run(r *SessionRunner) (stepResult *StepResult, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
|
||||||
r.summary.Success = false
|
|
||||||
}
|
|
||||||
stepResult.StepType = stepTypeAPI
|
stepResult.StepType = stepTypeAPI
|
||||||
}()
|
}()
|
||||||
// extend request with referenced API
|
// extend request with referenced API
|
||||||
|
|||||||
+3
-14
@@ -4,9 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/pkg/uixt"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/pkg/uixt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ios setting options
|
// ios setting options
|
||||||
@@ -559,7 +560,6 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
parser := s.GetParser()
|
|
||||||
|
|
||||||
var osType string
|
var osType string
|
||||||
var mobileStep *MobileStep
|
var mobileStep *MobileStep
|
||||||
@@ -590,17 +590,6 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err
|
|||||||
screenshots = append(screenshots, uiDriver.ScreenShots...)
|
screenshots = append(screenshots, uiDriver.ScreenShots...)
|
||||||
attachments["screenshots"] = screenshots
|
attachments["screenshots"] = screenshots
|
||||||
stepResult.Attachments = attachments
|
stepResult.Attachments = attachments
|
||||||
|
|
||||||
// update summary
|
|
||||||
s.summary.Records = append(s.summary.Records, stepResult)
|
|
||||||
s.summary.Stat.Total += 1
|
|
||||||
if stepResult.Success {
|
|
||||||
s.summary.Stat.Successes += 1
|
|
||||||
} else {
|
|
||||||
s.summary.Stat.Failures += 1
|
|
||||||
// update summary result to failed
|
|
||||||
s.summary.Success = false
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// prepare actions
|
// prepare actions
|
||||||
@@ -618,7 +607,7 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err
|
|||||||
|
|
||||||
// run actions
|
// run actions
|
||||||
for _, action := range actions {
|
for _, action := range actions {
|
||||||
if action.Params, err = parser.Parse(action.Params, stepVariables); err != nil {
|
if action.Params, err = s.parser.Parse(action.Params, stepVariables); err != nil {
|
||||||
return stepResult, errors.Wrap(err, "parse action params failed")
|
return stepResult, errors.Wrap(err, "parse action params failed")
|
||||||
}
|
}
|
||||||
if err := uiDriver.DoAction(action); err != nil {
|
if err := uiDriver.DoAction(action); err != nil {
|
||||||
|
|||||||
+2
-12
@@ -297,16 +297,6 @@ func runStepRequest(r *SessionRunner, step *TStep) (stepResult *StepResult, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
stepResult.Attachments = err.Error()
|
stepResult.Attachments = err.Error()
|
||||||
}
|
}
|
||||||
// update summary
|
|
||||||
r.summary.Records = append(r.summary.Records, stepResult)
|
|
||||||
r.summary.Stat.Total += 1
|
|
||||||
if stepResult.Success {
|
|
||||||
r.summary.Stat.Successes += 1
|
|
||||||
} else {
|
|
||||||
r.summary.Stat.Failures += 1
|
|
||||||
// update summary result to failed
|
|
||||||
r.summary.Success = false
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// override step variables
|
// override step variables
|
||||||
@@ -321,8 +311,8 @@ func runStepRequest(r *SessionRunner, step *TStep) (stepResult *StepResult, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
sessionData := newSessionData()
|
sessionData := newSessionData()
|
||||||
parser := r.GetParser()
|
parser := r.parser
|
||||||
config := r.GetConfig()
|
config := r.parsedConfig
|
||||||
|
|
||||||
rb := newRequestBuilder(parser, config, step.Request)
|
rb := newRequestBuilder(parser, config, step.Request)
|
||||||
rb.req.Method = string(step.Request.Method)
|
rb.req.Method = string(step.Request.Method)
|
||||||
|
|||||||
@@ -109,12 +109,6 @@ func (s *StepTestCaseWithOptionalArgs) Run(r *SessionRunner) (stepResult *StepRe
|
|||||||
// export testcase export variables
|
// export testcase export variables
|
||||||
stepResult.ExportVars = summary.InOut.ExportVars
|
stepResult.ExportVars = summary.InOut.ExportVars
|
||||||
|
|
||||||
// merge testcase summary
|
|
||||||
r.summary.Records = append(r.summary.Records, summary.Records...)
|
|
||||||
r.summary.Stat.Total += summary.Stat.Total
|
|
||||||
r.summary.Stat.Successes += summary.Stat.Successes
|
|
||||||
r.summary.Stat.Failures += summary.Stat.Failures
|
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
stepResult.Success = true
|
stepResult.Success = true
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-12
@@ -260,16 +260,6 @@ func runStepWebSocket(r *SessionRunner, step *TStep) (stepResult *StepResult, er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
stepResult.Attachments = err.Error()
|
stepResult.Attachments = err.Error()
|
||||||
}
|
}
|
||||||
// update summary
|
|
||||||
r.summary.Records = append(r.summary.Records, stepResult)
|
|
||||||
r.summary.Stat.Total += 1
|
|
||||||
if stepResult.Success {
|
|
||||||
r.summary.Stat.Successes += 1
|
|
||||||
} else {
|
|
||||||
r.summary.Stat.Failures += 1
|
|
||||||
// update summary result to failed
|
|
||||||
r.summary.Success = false
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// override step variables
|
// override step variables
|
||||||
@@ -279,8 +269,8 @@ func runStepWebSocket(r *SessionRunner, step *TStep) (stepResult *StepResult, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
sessionData := newSessionData()
|
sessionData := newSessionData()
|
||||||
parser := r.GetParser()
|
parser := r.parser
|
||||||
config := r.GetConfig()
|
config := r.parsedConfig
|
||||||
|
|
||||||
dummyReq := &Request{
|
dummyReq := &Request{
|
||||||
URL: step.WebSocket.URL,
|
URL: step.WebSocket.URL,
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package hrp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -359,61 +357,3 @@ func convertJmespathExpr(checkExpr string) string {
|
|||||||
}
|
}
|
||||||
return strings.Join(checkItems, ".")
|
return strings.Join(checkItems, ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadTestCases(iTestCases ...ITestCase) ([]*TestCase, error) {
|
|
||||||
testCases := make([]*TestCase, 0)
|
|
||||||
|
|
||||||
for _, iTestCase := range iTestCases {
|
|
||||||
if _, ok := iTestCase.(*TestCase); ok {
|
|
||||||
testcase, err := iTestCase.ToTestCase()
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("failed to convert ITestCase interface to TestCase struct")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
testCases = append(testCases, testcase)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// iTestCase should be a TestCasePath, file path or folder path
|
|
||||||
tcPath, ok := iTestCase.(*TestCasePath)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.New("invalid iTestCase type")
|
|
||||||
}
|
|
||||||
|
|
||||||
casePath := tcPath.GetPath()
|
|
||||||
err := fs.WalkDir(os.DirFS(casePath), ".", func(path string, dir fs.DirEntry, e error) error {
|
|
||||||
if dir == nil {
|
|
||||||
// casePath is a file other than a dir
|
|
||||||
path = casePath
|
|
||||||
} else if dir.IsDir() && path != "." && strings.HasPrefix(path, ".") {
|
|
||||||
// skip hidden folders
|
|
||||||
return fs.SkipDir
|
|
||||||
} else {
|
|
||||||
// casePath is a dir
|
|
||||||
path = filepath.Join(casePath, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore non-testcase files
|
|
||||||
ext := filepath.Ext(path)
|
|
||||||
if ext != ".yml" && ext != ".yaml" && ext != ".json" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// filtered testcases
|
|
||||||
testCasePath := TestCasePath(path)
|
|
||||||
tc, err := testCasePath.ToTestCase()
|
|
||||||
if err != nil {
|
|
||||||
log.Warn().Err(err).Str("path", path).Msg("load testcase failed")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
testCases = append(testCases, tc)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "read dir failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Int("count", len(testCases)).Msg("load testcases successfully")
|
|
||||||
return testCases, nil
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user