From c23053ca16e86db9c92106fb94f780299dda0812 Mon Sep 17 00:00:00 2001 From: debugtalk Date: Tue, 18 Oct 2022 15:51:56 +0800 Subject: [PATCH] refactor: update summary in controller --- hrp/internal/code/code.go | 8 ++--- hrp/loader.go | 69 +++++++++++++++++++++++++++++++++++++++ hrp/parser.go | 6 ++-- hrp/parser_test.go | 8 ++--- hrp/runner.go | 7 ++-- hrp/session.go | 40 ++++++++++++----------- hrp/step_api.go | 3 -- hrp/step_mobile_ui.go | 17 ++-------- hrp/step_request.go | 14 ++------ hrp/step_testcase.go | 6 ---- hrp/step_websocket.go | 14 ++------ hrp/testcase.go | 60 ---------------------------------- 12 files changed, 112 insertions(+), 140 deletions(-) create mode 100644 hrp/loader.go diff --git a/hrp/internal/code/code.go b/hrp/internal/code/code.go index 37d8d1ce..5d483978 100644 --- a/hrp/internal/code/code.go +++ b/hrp/internal/code/code.go @@ -6,8 +6,8 @@ import ( // general: [0, 20) const ( - SUCCESS = 0 - FAIL = 1 + Success = 0 + GeneralFail = 1 ) // loader: [20, 40) @@ -64,7 +64,7 @@ var errorsMap = map[error]int{ func GetErrorCode(err error) int { if err == nil { - return SUCCESS + return Success } e := errors.Cause(err) @@ -72,5 +72,5 @@ func GetErrorCode(err error) int { return code } - return FAIL + return GeneralFail } diff --git a/hrp/loader.go b/hrp/loader.go new file mode 100644 index 00000000..0f75ef95 --- /dev/null +++ b/hrp/loader.go @@ -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 +} diff --git a/hrp/parser.go b/hrp/parser.go index 99e4359b..a177c82c 100644 --- a/hrp/parser.go +++ b/hrp/parser.go @@ -190,7 +190,7 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{} return raw, err } - result, err := p.CallFunc(funcName, parsedArgs.([]interface{})...) + result, err := p.callFunc(funcName, parsedArgs.([]interface{})...) if err != nil { log.Error().Str("funcName", funcName).Interface("arguments", arguments). Err(err).Msg("call function failed") @@ -251,9 +251,9 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{} return parsedString, nil } -// CallFunc calls function with arguments +// callFunc calls function with arguments // 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 if p.plugin != nil { if p.plugin.Has(funcName) { diff --git a/hrp/parser_test.go b/hrp/parser_test.go index 5f27010b..79756c43 100644 --- a/hrp/parser_test.go +++ b/hrp/parser_test.go @@ -478,14 +478,14 @@ func TestCallBuiltinFunction(t *testing.T) { parser := newParser() // call function without arguments - _, err := parser.CallFunc("get_timestamp") + _, err := parser.callFunc("get_timestamp") if !assert.NoError(t, err) { t.Fatal() } // call function with one argument timeStart := time.Now() - _, err = parser.CallFunc("sleep", 1) + _, err = parser.callFunc("sleep", 1) if !assert.NoError(t, err) { t.Fatal() } @@ -494,7 +494,7 @@ func TestCallBuiltinFunction(t *testing.T) { } // 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) { t.Fatal() } @@ -503,7 +503,7 @@ func TestCallBuiltinFunction(t *testing.T) { } // 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) { t.Fatal() } diff --git a/hrp/runner.go b/hrp/runner.go index 5fd4a102..58559e85 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -317,9 +317,10 @@ func (r *HRPRunner) newCaseRunner(testcase *TestCase) (*testCaseRunner, error) { } type testCaseRunner struct { - testCase *TestCase - hrpRunner *HRPRunner - parser *Parser + testCase *TestCase + hrpRunner *HRPRunner + parser *Parser + parsedConfig *TConfig parametersIterator *ParametersIterator rootDir string // project root dir diff --git a/hrp/session.go b/hrp/session.go index 0a3b7fb5..e11a2958 100644 --- a/hrp/session.go +++ b/hrp/session.go @@ -35,14 +35,6 @@ func (r *SessionRunner) resetSession() { 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 { return r.hrpRunner.httpStatOn } @@ -74,31 +66,41 @@ func (r *SessionRunner) Start(givenVars map[string]interface{}) error { log.Info().Str("step", stepName). Str("type", string(step.Type())).Msg("run step start") + // run step stepResult, err := step.Run(r) 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(). Str("step", stepResult.Name). Str("type", string(stepResult.StepType)). Bool("success", false). Msg("run step end") + } - if r.hrpRunner.failfast { - return errors.Wrap(err, "abort running due to failfast setting") - } + // check if failfast + if err != nil && r.hrpRunner.failfast { + return errors.Wrap(err, "abort running due to failfast setting") } // update extracted variables for k, v := range stepResult.ExportVars { 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 diff --git a/hrp/step_api.go b/hrp/step_api.go index f31e96bd..f6640332 100644 --- a/hrp/step_api.go +++ b/hrp/step_api.go @@ -100,9 +100,6 @@ func (s *StepAPIWithOptionalArgs) Struct() *TStep { func (s *StepAPIWithOptionalArgs) Run(r *SessionRunner) (stepResult *StepResult, err error) { defer func() { - if err != nil { - r.summary.Success = false - } stepResult.StepType = stepTypeAPI }() // extend request with referenced API diff --git a/hrp/step_mobile_ui.go b/hrp/step_mobile_ui.go index 8b16a9ce..585d5fa2 100644 --- a/hrp/step_mobile_ui.go +++ b/hrp/step_mobile_ui.go @@ -4,9 +4,10 @@ import ( "fmt" "time" - "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" "github.com/pkg/errors" "github.com/rs/zerolog/log" + + "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" ) // ios setting options @@ -559,7 +560,6 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err if err != nil { return } - parser := s.GetParser() var osType string var mobileStep *MobileStep @@ -590,17 +590,6 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err screenshots = append(screenshots, uiDriver.ScreenShots...) attachments["screenshots"] = screenshots 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 @@ -618,7 +607,7 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err // run 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") } if err := uiDriver.DoAction(action); err != nil { diff --git a/hrp/step_request.go b/hrp/step_request.go index e5adf26c..7aed3f13 100644 --- a/hrp/step_request.go +++ b/hrp/step_request.go @@ -297,16 +297,6 @@ func runStepRequest(r *SessionRunner, step *TStep) (stepResult *StepResult, err if err != nil { 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 @@ -321,8 +311,8 @@ func runStepRequest(r *SessionRunner, step *TStep) (stepResult *StepResult, err } sessionData := newSessionData() - parser := r.GetParser() - config := r.GetConfig() + parser := r.parser + config := r.parsedConfig rb := newRequestBuilder(parser, config, step.Request) rb.req.Method = string(step.Request.Method) diff --git a/hrp/step_testcase.go b/hrp/step_testcase.go index 72f2c340..e0c7a346 100644 --- a/hrp/step_testcase.go +++ b/hrp/step_testcase.go @@ -109,12 +109,6 @@ func (s *StepTestCaseWithOptionalArgs) Run(r *SessionRunner) (stepResult *StepRe // export testcase export variables 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 { stepResult.Success = true } diff --git a/hrp/step_websocket.go b/hrp/step_websocket.go index 5da949f6..c953a1ce 100644 --- a/hrp/step_websocket.go +++ b/hrp/step_websocket.go @@ -260,16 +260,6 @@ func runStepWebSocket(r *SessionRunner, step *TStep) (stepResult *StepResult, er if err != nil { 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 @@ -279,8 +269,8 @@ func runStepWebSocket(r *SessionRunner, step *TStep) (stepResult *StepResult, er } sessionData := newSessionData() - parser := r.GetParser() - config := r.GetConfig() + parser := r.parser + config := r.parsedConfig dummyReq := &Request{ URL: step.WebSocket.URL, diff --git a/hrp/testcase.go b/hrp/testcase.go index 401b179b..b9733b57 100644 --- a/hrp/testcase.go +++ b/hrp/testcase.go @@ -2,8 +2,6 @@ package hrp import ( "fmt" - "io/fs" - "os" "path/filepath" "strings" @@ -359,61 +357,3 @@ func convertJmespathExpr(checkExpr string) string { } 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 -}