refactor: update summary in controller

This commit is contained in:
debugtalk
2022-10-18 16:07:21 +08:00
parent 792605a1dc
commit c23053ca16
12 changed files with 112 additions and 140 deletions
+4 -4
View File
@@ -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
} }
+69
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-3
View File
@@ -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
View File
@@ -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
View File
@@ -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)
-6
View File
@@ -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
View File
@@ -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,
-60
View File
@@ -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
}