diff --git a/hrp/internal/code/code.go b/hrp/internal/code/code.go index 5d483978..b2e6eb60 100644 --- a/hrp/internal/code/code.go +++ b/hrp/internal/code/code.go @@ -18,17 +18,33 @@ var ( ) // parser: [40, 60) +var ( + ParseError = errors.New("parse error") // 40 + ParseConfigError = errors.New("parse config error") // 41 + ParseStringError = errors.New("parse string failed") // 42 + ParseVariablesError = errors.New("parse variables failed") // 43 +) // runner: [60, 100) // ios related: [100, 130) var ( - IOSScreenShotError = errors.New("ios screenshot error") // 110 + IOSDeviceConnectionError = errors.New("ios device connection error") // 100 + IOSDeviceHTTPDriverError = errors.New("ios device HTTP driver error") // 101 + IOSDeviceUSBDriverError = errors.New("ios device USB driver error") // 102 + IOSScreenShotError = errors.New("ios screenshot error") // 110 + IOSCaptureLogError = errors.New("ios capture log error") // 111 + + MobileUIDriverError = errors.New("mobile UI driver error") // 120 + MobileUIValidationError = errors.New("mobile UI validation error") // 121 ) // android related: [130, 160) var ( - AndroidScreenShotError = errors.New("android screenshot error") // 150 + AndroidDeviceConnectionError = errors.New("android device connection error") // 130 + AndroidDeviceDriverError = errors.New("android device driver error") // 131 + AndroidScreenShotError = errors.New("android screenshot error") // 150 + AndroidCaptureLogError = errors.New("android capture log error") // 151 ) // OCR related: [160, 180) @@ -45,14 +61,28 @@ var ( // report related: [200, 220) var errorsMap = map[error]int{ + // loader LoadJSONError: 10, LoadYAMLError: 11, + // parser + ParseError: 40, + ParseConfigError: 41, + ParseStringError: 42, + ParseVariablesError: 43, + // ios related - IOSScreenShotError: 110, + IOSDeviceConnectionError: 100, + IOSDeviceHTTPDriverError: 101, + IOSDeviceUSBDriverError: 102, + IOSScreenShotError: 110, + IOSCaptureLogError: 111, // android related - AndroidScreenShotError: 130, + AndroidDeviceConnectionError: 130, + AndroidDeviceDriverError: 131, + AndroidScreenShotError: 150, + AndroidCaptureLogError: 151, // OCR related OCREnvMissedError: 160, diff --git a/hrp/internal/version/VERSION b/hrp/internal/version/VERSION index bd879d79..902617de 100644 --- a/hrp/internal/version/VERSION +++ b/hrp/internal/version/VERSION @@ -1 +1 @@ -v4.3.0-beta-10172144 \ No newline at end of file +v4.3.0-beta-10191154 \ No newline at end of file diff --git a/hrp/parser.go b/hrp/parser.go index a177c82c..290a5f07 100644 --- a/hrp/parser.go +++ b/hrp/parser.go @@ -13,9 +13,11 @@ import ( "github.com/httprunner/funplugin" "github.com/httprunner/funplugin/shared" "github.com/maja42/goval" + "github.com/pkg/errors" "github.com/rs/zerolog/log" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" + "github.com/httprunner/httprunner/v4/hrp/internal/code" ) func newParser() *Parser { @@ -183,18 +185,18 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{} argsStr := funcMatched[2] arguments, err := parseFunctionArguments(argsStr) if err != nil { - return raw, err + return raw, errors.Wrap(code.ParseStringError, err.Error()) } parsedArgs, err := p.Parse(arguments, variablesMapping) if err != nil { - return raw, err + return raw, errors.Wrap(code.ParseStringError, err.Error()) } result, err := p.callFunc(funcName, parsedArgs.([]interface{})...) if err != nil { log.Error().Str("funcName", funcName).Interface("arguments", arguments). Err(err).Msg("call function failed") - return raw, err + return raw, errors.Wrap(code.ParseStringError, err.Error()) } log.Info().Str("funcName", funcName).Interface("arguments", arguments). Interface("output", result).Msg("call function success") @@ -226,7 +228,8 @@ func (p *Parser) ParseString(raw string, variablesMapping map[string]interface{} } varValue, ok := variablesMapping[varName] if !ok { - return raw, fmt.Errorf("variable %s not found", varName) + return raw, errors.Wrap(code.ParseStringError, + fmt.Sprintf("variable %s not found", varName)) } if fmt.Sprintf("${%s}", varName) == raw || fmt.Sprintf("$%s", varName) == raw { @@ -428,7 +431,8 @@ func (p *Parser) ParseVariables(variables map[string]interface{}) (map[string]in // variables = {"key": ["$key", 2]} if _, ok := extractVarsSet[varName]; ok { log.Error().Interface("variables", variables).Msg("[parseVariables] variable self reference error") - return variables, fmt.Errorf("variable self reference: %v", varName) + return variables, errors.Wrap(code.ParseVariablesError, + fmt.Sprintf("variable self reference: %v", varName)) } // check if reference variable not in variables mapping @@ -443,7 +447,8 @@ func (p *Parser) ParseVariables(variables map[string]interface{}) (map[string]in } if len(undefinedVars) > 0 { log.Error().Interface("undefinedVars", undefinedVars).Msg("[parseVariables] variable not defined error") - return variables, fmt.Errorf("variable not defined: %v", undefinedVars) + return variables, errors.Wrap(code.ParseVariablesError, + fmt.Sprintf("variable not defined: %v", undefinedVars)) } parsedValue, err := p.Parse(varValue, parsedVariables) @@ -456,7 +461,7 @@ func (p *Parser) ParseVariables(variables map[string]interface{}) (map[string]in // check if circular reference exists if traverseRounds > len(variables) { log.Error().Msg("[parseVariables] circular reference error, break infinite loop!") - return variables, fmt.Errorf("circular reference") + return variables, errors.Wrap(code.ParseVariablesError, "circular reference") } } diff --git a/hrp/pkg/uixt/android_device.go b/hrp/pkg/uixt/android_device.go index 8fbd713b..492bf765 100644 --- a/hrp/pkg/uixt/android_device.go +++ b/hrp/pkg/uixt/android_device.go @@ -13,6 +13,7 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog/log" + "github.com/httprunner/httprunner/v4/hrp/internal/code" "github.com/httprunner/httprunner/v4/hrp/internal/json" "github.com/httprunner/httprunner/v4/hrp/internal/myexec" ) @@ -71,7 +72,8 @@ func GetAndroidDeviceOptions(dev *AndroidDevice) (deviceOptions []AndroidDeviceO func NewAndroidDevice(options ...AndroidDeviceOption) (device *AndroidDevice, err error) { deviceList, err := DeviceList() if err != nil { - return nil, fmt.Errorf("get attached devices failed: %v", err) + return nil, errors.Wrap(code.AndroidDeviceConnectionError, + fmt.Sprintf("get attached devices failed: %v", err)) } device = &AndroidDevice{ @@ -95,13 +97,14 @@ func NewAndroidDevice(options ...AndroidDeviceOption) (device *AndroidDevice, er return device, nil } - return nil, fmt.Errorf("device %s not found", device.SerialNumber) + return nil, errors.Wrap(code.AndroidDeviceConnectionError, + fmt.Sprintf("device %s not found", device.SerialNumber)) } func DeviceList() (devices []gadb.Device, err error) { var adbClient gadb.Client if adbClient, err = gadb.NewClientWith(AdbServerHost, AdbServerPort); err != nil { - return nil, err + return nil, errors.Wrap(code.AndroidDeviceConnectionError, err.Error()) } return adbClient.DeviceList() diff --git a/hrp/pkg/uixt/android_driver.go b/hrp/pkg/uixt/android_driver.go index 526bfc32..904b550f 100644 --- a/hrp/pkg/uixt/android_driver.go +++ b/hrp/pkg/uixt/android_driver.go @@ -963,7 +963,12 @@ func (ud *uiaDriver) Wait(condition Condition) error { func (ud *uiaDriver) StartCaptureLog(identifier ...string) (err error) { log.Info().Msg("start adb log recording") err = ud.logcat.CatchLogcat() - return + if err != nil { + err = errors.Wrap(code.IOSCaptureLogError, + fmt.Sprintf("start adb log recording failed: %v", err)) + return err + } + return nil } func (ud *uiaDriver) StopCaptureLog() (result interface{}, err error) { @@ -971,6 +976,8 @@ func (ud *uiaDriver) StopCaptureLog() (result interface{}, err error) { err = ud.logcat.Stop() if err != nil { log.Error().Err(err).Msg("failed to get adb log recording") + err = errors.Wrap(code.IOSCaptureLogError, + fmt.Sprintf("get adb log recording failed: %v", err)) return "", err } content := ud.logcat.logBuffer.String() diff --git a/hrp/pkg/uixt/ios_device.go b/hrp/pkg/uixt/ios_device.go index 0b2a4d50..fb8afdd6 100644 --- a/hrp/pkg/uixt/ios_device.go +++ b/hrp/pkg/uixt/ios_device.go @@ -20,6 +20,7 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog/log" + "github.com/httprunner/httprunner/v4/hrp/internal/code" "github.com/httprunner/httprunner/v4/hrp/internal/env" "github.com/httprunner/httprunner/v4/hrp/internal/json" ) @@ -106,11 +107,13 @@ func WithPerfOptions(options ...giDevice.PerfOption) IOSDeviceOption { func IOSDevices(udid ...string) (devices []giDevice.Device, err error) { var usbmux giDevice.Usbmux if usbmux, err = giDevice.NewUsbmux(); err != nil { - return nil, fmt.Errorf("init usbmux failed: %v", err) + return nil, errors.Wrap(code.IOSDeviceConnectionError, + fmt.Sprintf("init usbmux failed: %v", err)) } if devices, err = usbmux.Devices(); err != nil { - return nil, fmt.Errorf("list ios devices failed: %v", err) + return nil, errors.Wrap(code.IOSDeviceConnectionError, + fmt.Sprintf("list ios devices failed: %v", err)) } // filter by udid @@ -185,7 +188,8 @@ func NewIOSDevice(options ...IOSDeviceOption) (device *IOSDevice, err error) { return device, nil } - return nil, fmt.Errorf("device %s not found", device.UDID) + return nil, errors.Wrap(code.IOSDeviceConnectionError, + fmt.Sprintf("device %s not found", device.UDID)) } type IOSDevice struct { @@ -230,13 +234,15 @@ func (dev *IOSDevice) NewDriver(capabilities Capabilities) (driverExt *DriverExt if dev.ResetHomeOnStartup { log.Info().Msg("go back to home screen") if err = driver.Homescreen(); err != nil { - return nil, errors.Wrap(err, "failed to go back to home screen") + return nil, errors.Wrap(code.MobileUIDriverError, + fmt.Sprintf("go back to home screen failed: %v", err)) } } driverExt, err = Extend(driver) if err != nil { - return nil, errors.Wrap(err, "failed to extend WebDriver") + return nil, errors.Wrap(code.MobileUIDriverError, + fmt.Sprintf("extend WebDriver failed: %v", err)) } settings, err := driverExt.Driver.SetAppiumSettings(map[string]interface{}{ "snapshotMaxDepth": dev.SnapshotMaxDepth, @@ -380,17 +386,21 @@ func (dev *IOSDevice) perfOpitons() (perfOptions []giDevice.PerfOption) { func (dev *IOSDevice) NewHTTPDriver(capabilities Capabilities) (driver WebDriver, err error) { localPort, err := getFreePort() if err != nil { - return nil, errors.Wrap(err, "get free port failed") + return nil, errors.Wrap(code.IOSDeviceHTTPDriverError, + fmt.Sprintf("get free port failed: %v", err)) } if err = dev.forward(localPort, dev.Port); err != nil { - return nil, errors.Wrap(err, "forward tcp port failed") + return nil, errors.Wrap(code.IOSDeviceHTTPDriverError, + fmt.Sprintf("forward tcp port failed: %v", err)) } localMjpegPort, err := getFreePort() if err != nil { - return nil, errors.Wrap(err, "get free port failed") + return nil, errors.Wrap(code.IOSDeviceHTTPDriverError, + fmt.Sprintf("get free port failed: %v", err)) } if err = dev.forward(localMjpegPort, dev.MjpegPort); err != nil { - return nil, errors.Wrap(err, "forward tcp port failed") + return nil, errors.Wrap(code.IOSDeviceHTTPDriverError, + fmt.Sprintf("forward tcp port failed: %v", err)) } log.Info().Interface("capabilities", capabilities). @@ -402,11 +412,11 @@ func (dev *IOSDevice) NewHTTPDriver(capabilities Capabilities) (driver WebDriver host := "127.0.0.1" if wd.urlPrefix, err = url.Parse(fmt.Sprintf("http://%s:%d", host, localPort)); err != nil { - return nil, err + return nil, errors.Wrap(code.IOSDeviceHTTPDriverError, err.Error()) } var sessionInfo SessionInfo if sessionInfo, err = wd.NewSession(capabilities); err != nil { - return nil, err + return nil, errors.Wrap(code.IOSDeviceHTTPDriverError, err.Error()) } wd.sessionId = sessionInfo.SessionId @@ -414,7 +424,7 @@ func (dev *IOSDevice) NewHTTPDriver(capabilities Capabilities) (driver WebDriver "tcp", fmt.Sprintf("%s:%d", host, localMjpegPort), ); err != nil { - return nil, err + return nil, errors.Wrap(code.IOSDeviceHTTPDriverError, err.Error()) } wd.mjpegClient = convertToHTTPClient(wd.mjpegHTTPConn) @@ -428,23 +438,25 @@ func (dev *IOSDevice) NewUSBDriver(capabilities Capabilities) (driver WebDriver, wd := new(wdaDriver) if wd.defaultConn, err = dev.d.NewConnect(dev.Port, 0); err != nil { - return nil, fmt.Errorf("connect port %d failed: %w", - dev.Port, err) + return nil, errors.Wrap(code.IOSDeviceUSBDriverError, + fmt.Sprintf("connect port %d failed: %v", dev.Port, err)) } wd.client = convertToHTTPClient(wd.defaultConn.RawConn()) if wd.mjpegUSBConn, err = dev.d.NewConnect(dev.MjpegPort, 0); err != nil { - return nil, fmt.Errorf("connect MJPEG port %d failed: %w", - dev.MjpegPort, err) + return nil, errors.Wrap(code.IOSDeviceUSBDriverError, + fmt.Sprintf("connect MJPEG port %d failed: %v", dev.MjpegPort, err)) } wd.mjpegClient = convertToHTTPClient(wd.mjpegUSBConn.RawConn()) if wd.urlPrefix, err = url.Parse("http://" + dev.UDID); err != nil { - return nil, err + return nil, errors.Wrap(code.IOSDeviceUSBDriverError, err.Error()) + } + if _, err = wd.NewSession(capabilities); err != nil { + return nil, errors.Wrap(code.IOSDeviceUSBDriverError, err.Error()) } - _, err = wd.NewSession(capabilities) - return wd, err + return wd, nil } func (dExt *DriverExt) ConnectMjpegStream(httpClient *http.Client) (err error) { diff --git a/hrp/pkg/uixt/ios_driver.go b/hrp/pkg/uixt/ios_driver.go index b4704f77..72da3928 100644 --- a/hrp/pkg/uixt/ios_driver.go +++ b/hrp/pkg/uixt/ios_driver.go @@ -858,7 +858,8 @@ func (wd *wdaDriver) StartCaptureLog(identifier ...string) error { data := map[string]interface{}{"action": "start", "type": 2, "identifier": identifier[0]} _, err := wd.triggerWDALog(data) if err != nil { - return errors.Wrap(err, "failed to start WDA log recording") + return errors.Wrap(code.IOSCaptureLogError, + fmt.Sprintf("start WDA log recording failed: %v", err)) } return nil @@ -875,12 +876,14 @@ func (wd *wdaDriver) StopCaptureLog() (result interface{}, err error) { rawResp, err := wd.triggerWDALog(data) if err != nil { log.Error().Err(err).Bytes("rawResp", rawResp).Msg("failed to get WDA logs") - return "", errors.Wrap(err, "failed to get WDA logs") + return "", errors.Wrap(code.IOSCaptureLogError, + fmt.Sprintf("get WDA logs failed: %v", err)) } reply := new(wdaResponse) if err = json.Unmarshal(rawResp, reply); err != nil { log.Error().Err(err).Bytes("rawResp", rawResp).Msg("failed to json.Unmarshal WDA logs") - return reply, err + return reply, errors.Wrap(code.IOSCaptureLogError, + fmt.Sprintf("json.Unmarshal WDA logs failed: %v", err)) } log.Info().Interface("value", reply.Value).Msg("get WDA log response") return reply.Value, nil diff --git a/hrp/runner.go b/hrp/runner.go index 1b164226..63e5b407 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -560,7 +560,7 @@ func (r *SessionRunner) ParseStepVariables(stepVariables map[string]interface{}) if err != nil { log.Error().Interface("variables", r.caseRunner.parsedConfig.Variables). Err(err).Msg("parse step variables failed") - return nil, err + return nil, errors.Wrap(err, "parse step variables failed") } return parsedVariables, nil } diff --git a/hrp/step_mobile_ui.go b/hrp/step_mobile_ui.go index a6dad716..90985d9e 100644 --- a/hrp/step_mobile_ui.go +++ b/hrp/step_mobile_ui.go @@ -7,6 +7,7 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog/log" + "github.com/httprunner/httprunner/v4/hrp/internal/code" "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" ) @@ -609,10 +610,11 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err // run actions for _, action := range actions { if action.Params, err = s.caseRunner.parser.Parse(action.Params, stepVariables); err != nil { - return stepResult, errors.Wrap(err, "parse action params failed") + return stepResult, errors.Wrap(code.ParseError, + fmt.Sprintf("parse action params failed: %v", err)) } if err := uiDriver.DoAction(action); err != nil { - return stepResult, err + return stepResult, errors.Wrap(code.MobileUIDriverError, err.Error()) } } @@ -629,6 +631,7 @@ func runStepMobileUI(s *SessionRunner, step *TStep) (stepResult *StepResult, err // validate validateResults, err := validateUI(uiDriver, step.Validators) if err != nil { + err = errors.Wrap(code.MobileUIValidationError, err.Error()) return } sessionData := newSessionData() diff --git a/httprunner/__init__.py b/httprunner/__init__.py index c0be7a21..249a8d92 100644 --- a/httprunner/__init__.py +++ b/httprunner/__init__.py @@ -1,4 +1,4 @@ -__version__ = "v4.3.0-beta-10172144" +__version__ = "v4.3.0-beta-10191154" __description__ = "One-stop solution for HTTP(S) testing." diff --git a/pyproject.toml b/pyproject.toml index 747bbbfb..43999353 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "httprunner" -version = "v4.3.0-beta-10172144" +version = "v4.3.0-beta-10191154" description = "One-stop solution for HTTP(S) testing." license = "Apache-2.0" readme = "README.md"