diff --git a/hrp/cmd/cli/main.go b/hrp/cmd/cli/main.go index 63f5c9bd..453891a1 100644 --- a/hrp/cmd/cli/main.go +++ b/hrp/cmd/cli/main.go @@ -1,6 +1,7 @@ package main import ( + "os" "time" "github.com/getsentry/sentry-go" @@ -20,5 +21,5 @@ func main() { } }() - cmd.Execute() + os.Exit(cmd.Execute()) } diff --git a/hrp/cmd/root.go b/hrp/cmd/root.go index 616fd0ab..2cc888e8 100644 --- a/hrp/cmd/root.go +++ b/hrp/cmd/root.go @@ -11,6 +11,7 @@ import ( "github.com/httprunner/httprunner/v4/hrp/cmd/adb" "github.com/httprunner/httprunner/v4/hrp/cmd/ios" + "github.com/httprunner/httprunner/v4/hrp/internal/code" "github.com/httprunner/httprunner/v4/hrp/internal/version" ) @@ -45,7 +46,8 @@ Copyright 2017 debugtalk`, } }, Version: version.VERSION, - TraverseChildren: true, + TraverseChildren: true, // parses flags on all parents before executing child command + SilenceUsage: true, // silence usage when an error occurs } var ( @@ -56,7 +58,7 @@ var ( // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { +func Execute() int { rootCmd.PersistentFlags().StringVarP(&logLevel, "log-level", "l", "INFO", "set log level") rootCmd.PersistentFlags().BoolVar(&logJSON, "log-json", false, "set log to json format") rootCmd.PersistentFlags().StringVar(&venv, "venv", "", "specify python3 venv path") @@ -64,9 +66,8 @@ func Execute() { ios.Init(rootCmd) adb.Init(rootCmd) - if err := rootCmd.Execute(); err != nil { - os.Exit(1) - } + err := rootCmd.Execute() + return code.GetErrorCode(err) } func setLogLevel(level string) { diff --git a/hrp/cmd/run.go b/hrp/cmd/run.go index c628f93a..5a7b4f8e 100644 --- a/hrp/cmd/run.go +++ b/hrp/cmd/run.go @@ -1,8 +1,6 @@ package cmd import ( - "os" - "github.com/spf13/cobra" "github.com/httprunner/httprunner/v4/hrp" @@ -20,17 +18,14 @@ var runCmd = &cobra.Command{ PreRun: func(cmd *cobra.Command, args []string) { setLogLevel(logLevel) }, - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { var paths []hrp.ITestCase for _, arg := range args { path := hrp.TestCasePath(arg) paths = append(paths, &path) } runner := makeHRPRunner() - err := runner.Run(paths...) - if err != nil { - os.Exit(1) - } + return runner.Run(paths...) }, } diff --git a/hrp/internal/code/code.go b/hrp/internal/code/code.go index ef009358..37d8d1ce 100644 --- a/hrp/internal/code/code.go +++ b/hrp/internal/code/code.go @@ -21,30 +21,45 @@ var ( // runner: [60, 100) -// ios related: [100, 120) +// ios related: [100, 130) var ( - IOSScreenShotError = errors.New("ios screenshot error") // 100 + IOSScreenShotError = errors.New("ios screenshot error") // 110 ) -// android related: [120, 140) - -// OCR related: [140, 160) +// android related: [130, 160) var ( - OCREnvMissedError = errors.New("veDEM OCR env missed error") // 140 - OCRRequestError = errors.New("vedem ocr prepare request error") // 141 - OCRServiceConnectionError = errors.New("vedem ocr service connect error") // 142 - OCRResponseStatusCodeNot200 = errors.New("vedem ocr response status code is not 200") // 143 - OCRResponseError = errors.New("vedem ocr parse response error") // 143 - OCRTextNotFoundError = errors.New("vedem ocr text not found") // 144 + AndroidScreenShotError = errors.New("android screenshot error") // 150 ) -// CV related: [160, 180) +// OCR related: [160, 180) +var ( + OCREnvMissedError = errors.New("veDEM OCR env missed error") // 160 + OCRRequestError = errors.New("vedem ocr prepare request error") // 161 + OCRServiceConnectionError = errors.New("vedem ocr service connect error") // 162 + OCRResponseError = errors.New("vedem ocr parse response error") // 163 + OCRTextNotFoundError = errors.New("vedem ocr text not found") // 164 +) + +// CV related: [180, 200) // report related: [200, 220) var errorsMap = map[error]int{ LoadJSONError: 10, LoadYAMLError: 11, + + // ios related + IOSScreenShotError: 110, + + // android related + AndroidScreenShotError: 130, + + // OCR related + OCREnvMissedError: 160, + OCRRequestError: 161, + OCRServiceConnectionError: 162, + OCRResponseError: 163, + OCRTextNotFoundError: 164, } func GetErrorCode(err error) int { diff --git a/hrp/internal/version/VERSION b/hrp/internal/version/VERSION index a28eeaba..bd879d79 100644 --- a/hrp/internal/version/VERSION +++ b/hrp/internal/version/VERSION @@ -1 +1 @@ -v4.3.0-beta-10161439 \ No newline at end of file +v4.3.0-beta-10172144 \ No newline at end of file diff --git a/hrp/pkg/uixt/android_driver.go b/hrp/pkg/uixt/android_driver.go index 3f1bdea0..526bfc32 100644 --- a/hrp/pkg/uixt/android_driver.go +++ b/hrp/pkg/uixt/android_driver.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/base64" "encoding/json" - "errors" "fmt" "net" "net/url" @@ -13,7 +12,10 @@ import ( "time" "github.com/electricbubble/gadb" + "github.com/pkg/errors" "github.com/rs/zerolog/log" + + "github.com/httprunner/httprunner/v4/hrp/internal/code" ) var errDriverNotImplemented = errors.New("driver method not implemented") @@ -860,7 +862,8 @@ func (ud *uiaDriver) Screenshot() (raw *bytes.Buffer, err error) { // register(getHandler, new CaptureScreenshot("/wd/hub/session/:sessionId/screenshot")) var rawResp rawResponse if rawResp, err = ud.httpGET("/session", ud.sessionId, "screenshot"); err != nil { - return nil, err + return nil, errors.Wrap(code.AndroidScreenShotError, + fmt.Sprintf("get UIA screenshot data failed: %v", err)) } reply := new(struct{ Value string }) if err = json.Unmarshal(rawResp, reply); err != nil { @@ -869,7 +872,8 @@ func (ud *uiaDriver) Screenshot() (raw *bytes.Buffer, err error) { var decodeStr []byte if decodeStr, err = base64.StdEncoding.DecodeString(reply.Value); err != nil { - return nil, err + return nil, errors.Wrap(code.AndroidScreenShotError, + fmt.Sprintf("decode UIA screenshot data failed: %v", err)) } raw = bytes.NewBuffer(decodeStr) diff --git a/hrp/pkg/uixt/ios_device.go b/hrp/pkg/uixt/ios_device.go index b02a34db..0b2a4d50 100644 --- a/hrp/pkg/uixt/ios_device.go +++ b/hrp/pkg/uixt/ios_device.go @@ -34,7 +34,7 @@ const ( // It may help to prevent out of memory or timeout errors while getting the elements source tree, // but it might restrict the depth of source tree. // A part of elements source tree might be lost if the value was too small. Defaults to 50 - snapshotMaxDepth = 16 + snapshotMaxDepth = 10 // Allows to customize accept/dismiss alert button selector. // It helps you to handle an arbitrary element as accept button in accept alert command. // The selector should be a valid class chain expression, where the search root is the alert element itself. diff --git a/hrp/pkg/uixt/ocr_vedem.go b/hrp/pkg/uixt/ocr_vedem.go index 1a2dc00f..1bae01ad 100644 --- a/hrp/pkg/uixt/ocr_vedem.go +++ b/hrp/pkg/uixt/ocr_vedem.go @@ -96,7 +96,11 @@ func (s *veDEMOCRService) getOCRResult(imageBuf []byte) ([]OCRResult, error) { if err == nil { break } - logID := getLogID(resp.Header) + + var logID string + if resp != nil { + logID = getLogID(resp.Header) + } log.Error().Err(err). Str("logID", logID). Int("imageBufSize", size). @@ -116,7 +120,7 @@ func (s *veDEMOCRService) getOCRResult(imageBuf []byte) ([]OCRResult, error) { } if resp.StatusCode != http.StatusOK { - return nil, errors.Wrap(code.OCRResponseStatusCodeNot200, + return nil, errors.Wrap(code.OCRResponseError, fmt.Sprintf("unexpected response status code: %d, results: %v", resp.StatusCode, string(results))) } @@ -258,8 +262,8 @@ func (s *veDEMOCRService) FindTexts(texts []string, imageBuf []byte, options ... } if !success { - return rects, - fmt.Errorf("texts %s not found in %v", texts, ocrTexts) + return rects, errors.Wrap(code.OCRTextNotFoundError, + fmt.Sprintf("texts %s not found in %v", texts, ocrTexts)) } return rects, nil diff --git a/hrp/pkg/uixt/swipe.go b/hrp/pkg/uixt/swipe.go index bd1aedf9..a7187045 100644 --- a/hrp/pkg/uixt/swipe.go +++ b/hrp/pkg/uixt/swipe.go @@ -8,6 +8,7 @@ import ( "github.com/rs/zerolog/log" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/code" ) func assertRelative(p float64) bool { @@ -97,7 +98,8 @@ func (dExt *DriverExt) SwipeUntil(direction interface{}, findCondition Action, f // wait for swipe action to completed and content to load completely time.Sleep(time.Duration(1000*interval) * time.Millisecond) } - return fmt.Errorf("swipe %s %d times, match condition failed", direction, maxRetryTimes) + return errors.Wrap(code.OCRTextNotFoundError, + fmt.Sprintf("swipe %s %d times, match condition failed", direction, maxRetryTimes)) } func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action, options ...DataOption) error { @@ -118,7 +120,9 @@ func (dExt *DriverExt) LoopUntil(findAction, findCondition, foundAction Action, // wait interval between each findAction time.Sleep(time.Duration(1000*interval) * time.Millisecond) } - return fmt.Errorf("loop %d times, match find condition failed", maxRetryTimes) + + return errors.Wrap(code.OCRTextNotFoundError, + fmt.Sprintf("loop %d times, match find condition failed", maxRetryTimes)) } func (dExt *DriverExt) swipeToTapApp(appName string, action MobileAction) error { diff --git a/httprunner/__init__.py b/httprunner/__init__.py index 4592b08c..c0be7a21 100644 --- a/httprunner/__init__.py +++ b/httprunner/__init__.py @@ -1,4 +1,4 @@ -__version__ = "v4.3.0-beta-10161439" +__version__ = "v4.3.0-beta-10172144" __description__ = "One-stop solution for HTTP(S) testing." diff --git a/pyproject.toml b/pyproject.toml index c3339ecf..747bbbfb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "httprunner" -version = "v4.3.0-beta-10161439" +version = "v4.3.0-beta-10172144" description = "One-stop solution for HTTP(S) testing." license = "Apache-2.0" readme = "README.md"