From 52b45a55d2e4033ab4f04127350dfa0d34fb94bf Mon Sep 17 00:00:00 2001 From: "lilong.129" Date: Sun, 10 Nov 2024 00:12:44 +0800 Subject: [PATCH] refactor: initUIClient --- hrp/internal/version/VERSION | 2 +- hrp/pkg/uixt/android_device.go | 38 ++++++------ hrp/pkg/uixt/harmony_device.go | 26 ++++---- hrp/pkg/uixt/ios_device.go | 74 +++++++++++------------ hrp/runner.go | 47 +-------------- hrp/step_mobile_ui.go | 105 ++++++++++++++++++++------------- 6 files changed, 138 insertions(+), 154 deletions(-) diff --git a/hrp/internal/version/VERSION b/hrp/internal/version/VERSION index 4e808fb4..7a2d0a5a 100644 --- a/hrp/internal/version/VERSION +++ b/hrp/internal/version/VERSION @@ -1 +1 @@ -v5.0.0+2411092321 +v5.0.0+2411100026 diff --git a/hrp/pkg/uixt/android_device.go b/hrp/pkg/uixt/android_device.go index 70a4cc19..1f59ed1a 100644 --- a/hrp/pkg/uixt/android_device.go +++ b/hrp/pkg/uixt/android_device.go @@ -86,25 +86,6 @@ func WithAdbLogOn(logOn bool) AndroidDeviceOption { } } -func GetAndroidDeviceOptions(dev *AndroidDevice) (deviceOptions []AndroidDeviceOption) { - if dev.SerialNumber != "" { - deviceOptions = append(deviceOptions, WithSerialNumber(dev.SerialNumber)) - } - if dev.UIA2 { - deviceOptions = append(deviceOptions, WithUIA2(true)) - } - if dev.UIA2IP != "" { - deviceOptions = append(deviceOptions, WithUIA2IP(dev.UIA2IP)) - } - if dev.UIA2Port != 0 { - deviceOptions = append(deviceOptions, WithUIA2Port(dev.UIA2Port)) - } - if dev.LogOn { - deviceOptions = append(deviceOptions, WithAdbLogOn(true)) - } - return -} - func NewAndroidDevice(options ...AndroidDeviceOption) (device *AndroidDevice, err error) { device = &AndroidDevice{ UIA2IP: UIA2ServerHost, @@ -191,6 +172,25 @@ type AndroidDevice struct { IgnorePopup bool `json:"ignore_popup,omitempty" yaml:"ignore_popup,omitempty"` } +func (dev *AndroidDevice) Options() (deviceOptions []AndroidDeviceOption) { + if dev.SerialNumber != "" { + deviceOptions = append(deviceOptions, WithSerialNumber(dev.SerialNumber)) + } + if dev.UIA2 { + deviceOptions = append(deviceOptions, WithUIA2(true)) + } + if dev.UIA2IP != "" { + deviceOptions = append(deviceOptions, WithUIA2IP(dev.UIA2IP)) + } + if dev.UIA2Port != 0 { + deviceOptions = append(deviceOptions, WithUIA2Port(dev.UIA2Port)) + } + if dev.LogOn { + deviceOptions = append(deviceOptions, WithAdbLogOn(true)) + } + return +} + func (dev *AndroidDevice) Init() error { dev.d.RunShellCommand("ime", "enable", "io.appium.settings/.UnicodeIME") dev.d.RunShellCommand("rm", "-r", config.DeviceActionLogFilePath) diff --git a/hrp/pkg/uixt/harmony_device.go b/hrp/pkg/uixt/harmony_device.go index 99955672..a4dbd220 100644 --- a/hrp/pkg/uixt/harmony_device.go +++ b/hrp/pkg/uixt/harmony_device.go @@ -22,6 +22,19 @@ type HarmonyDevice struct { LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"` } +func (dev *HarmonyDevice) Options() (deviceOptions []HarmonyDeviceOption) { + if dev.ConnectKey != "" { + deviceOptions = append(deviceOptions, WithConnectKey(dev.ConnectKey)) + } + if dev.IgnorePopup { + deviceOptions = append(deviceOptions, WithIgnorePopup(true)) + } + if dev.LogOn { + deviceOptions = append(deviceOptions, WithLogOn(true)) + } + return +} + type HarmonyDeviceOption func(*HarmonyDevice) func WithConnectKey(connectKey string) HarmonyDeviceOption { @@ -42,19 +55,6 @@ func WithLogOn(logOn bool) HarmonyDeviceOption { } } -func GetHarmonyDeviceOptions(dev *HarmonyDevice) (deviceOptions []HarmonyDeviceOption) { - if dev.ConnectKey != "" { - deviceOptions = append(deviceOptions, WithConnectKey(dev.ConnectKey)) - } - if dev.IgnorePopup { - deviceOptions = append(deviceOptions, WithIgnorePopup(true)) - } - if dev.LogOn { - deviceOptions = append(deviceOptions, WithLogOn(true)) - } - return -} - func NewHarmonyDevice(options ...HarmonyDeviceOption) (device *HarmonyDevice, err error) { device = &HarmonyDevice{} for _, option := range options { diff --git a/hrp/pkg/uixt/ios_device.go b/hrp/pkg/uixt/ios_device.go index 8b0e0735..d2566e12 100644 --- a/hrp/pkg/uixt/ios_device.go +++ b/hrp/pkg/uixt/ios_device.go @@ -182,43 +182,6 @@ func GetIOSDevices(udid ...string) (devices []gidevice.Device, err error) { return deviceList, nil } -func GetIOSDeviceOptions(dev *IOSDevice) (deviceOptions []IOSDeviceOption) { - if dev.UDID != "" { - deviceOptions = append(deviceOptions, WithUDID(dev.UDID)) - } - if dev.Port != 0 { - deviceOptions = append(deviceOptions, WithWDAPort(dev.Port)) - } - if dev.MjpegPort != 0 { - deviceOptions = append(deviceOptions, WithWDAMjpegPort(dev.MjpegPort)) - } - if dev.LogOn { - deviceOptions = append(deviceOptions, WithWDALogOn(true)) - } - if dev.PerfOptions != nil { - deviceOptions = append(deviceOptions, WithIOSPerfOptions(dev.perfOpitons()...)) - } - if dev.PcapOptions != nil { - deviceOptions = append(deviceOptions, WithIOSPcapOptions(dev.pcapOpitons()...)) - } - if dev.XCTestBundleID != "" { - deviceOptions = append(deviceOptions, WithXCTest(dev.XCTestBundleID)) - } - if dev.ResetHomeOnStartup { - deviceOptions = append(deviceOptions, WithResetHomeOnStartup(true)) - } - if dev.SnapshotMaxDepth != 0 { - deviceOptions = append(deviceOptions, WithSnapshotMaxDepth(dev.SnapshotMaxDepth)) - } - if dev.AcceptAlertButtonSelector != "" { - deviceOptions = append(deviceOptions, WithAcceptAlertButtonSelector(dev.AcceptAlertButtonSelector)) - } - if dev.DismissAlertButtonSelector != "" { - deviceOptions = append(deviceOptions, WithDismissAlertButtonSelector(dev.DismissAlertButtonSelector)) - } - return -} - func NewIOSDevice(options ...IOSDeviceOption) (device *IOSDevice, err error) { device = &IOSDevice{ Port: defaultWDAPort, @@ -296,6 +259,43 @@ type IOSDevice struct { pcapFile string // saved pcap file path } +func (dev *IOSDevice) Options() (deviceOptions []IOSDeviceOption) { + if dev.UDID != "" { + deviceOptions = append(deviceOptions, WithUDID(dev.UDID)) + } + if dev.Port != 0 { + deviceOptions = append(deviceOptions, WithWDAPort(dev.Port)) + } + if dev.MjpegPort != 0 { + deviceOptions = append(deviceOptions, WithWDAMjpegPort(dev.MjpegPort)) + } + if dev.LogOn { + deviceOptions = append(deviceOptions, WithWDALogOn(true)) + } + if dev.PerfOptions != nil { + deviceOptions = append(deviceOptions, WithIOSPerfOptions(dev.perfOpitons()...)) + } + if dev.PcapOptions != nil { + deviceOptions = append(deviceOptions, WithIOSPcapOptions(dev.pcapOpitons()...)) + } + if dev.XCTestBundleID != "" { + deviceOptions = append(deviceOptions, WithXCTest(dev.XCTestBundleID)) + } + if dev.ResetHomeOnStartup { + deviceOptions = append(deviceOptions, WithResetHomeOnStartup(true)) + } + if dev.SnapshotMaxDepth != 0 { + deviceOptions = append(deviceOptions, WithSnapshotMaxDepth(dev.SnapshotMaxDepth)) + } + if dev.AcceptAlertButtonSelector != "" { + deviceOptions = append(deviceOptions, WithAcceptAlertButtonSelector(dev.AcceptAlertButtonSelector)) + } + if dev.DismissAlertButtonSelector != "" { + deviceOptions = append(deviceOptions, WithDismissAlertButtonSelector(dev.DismissAlertButtonSelector)) + } + return +} + func (dev *IOSDevice) Init() error { return nil } diff --git a/hrp/runner.go b/hrp/runner.go index fe560a95..ae7dbf95 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -26,7 +26,6 @@ import ( "github.com/httprunner/httprunner/v4/hrp/code" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" "github.com/httprunner/httprunner/v4/hrp/internal/version" - "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" ) // Run starts to run testcase with default configs. @@ -407,69 +406,29 @@ func (r *CaseRunner) parseConfig() (parsedConfig *TConfig, err error) { } r.parametersIterator = parametersIterator - // init android devices + // parse android devices config for _, androidDevice := range parsedConfig.Android { err := r.parseDeviceConfig(androidDevice, parsedConfig.Variables) if err != nil { return nil, errors.Wrap(code.InvalidCaseError, fmt.Sprintf("parse android config failed: %v", err)) } - - device, err := uixt.NewAndroidDevice( - uixt.GetAndroidDeviceOptions(androidDevice)...) - if err != nil { - return nil, errors.Wrap(err, "init android device failed") - } - if err := device.Init(); err != nil { - return nil, err - } - client, err := device.NewDriver(uixt.WithDriverPlugin(r.parser.plugin)) - if err != nil { - return nil, errors.Wrap(err, "init android driver failed") - } - uiClients[device.SerialNumber] = client } - // init iOS devices + // parse iOS devices config for _, iosDevice := range parsedConfig.IOS { err := r.parseDeviceConfig(iosDevice, parsedConfig.Variables) if err != nil { return nil, errors.Wrap(code.InvalidCaseError, fmt.Sprintf("parse ios config failed: %v", err)) } - device, err := uixt.NewIOSDevice( - uixt.GetIOSDeviceOptions(iosDevice)...) - if err != nil { - return nil, errors.Wrap(err, "init ios device failed") - } - if err := device.Init(); err != nil { - return nil, err - } - client, err := device.NewDriver(uixt.WithDriverPlugin(r.parser.plugin)) - if err != nil { - return nil, errors.Wrap(err, "init ios driver failed") - } - uiClients[device.UDID] = client } - // init harmony devices + // parse harmony devices config for _, harmonyDevice := range parsedConfig.Harmony { err := r.parseDeviceConfig(harmonyDevice, parsedConfig.Variables) if err != nil { return nil, errors.Wrap(code.InvalidCaseError, fmt.Sprintf("parse harmony config failed: %v", err)) } - device, err := uixt.NewHarmonyDevice( - uixt.GetHarmonyDeviceOptions(harmonyDevice)...) - if err != nil { - return nil, errors.Wrap(err, "init harmony device failed") - } - if err := device.Init(); err != nil { - return nil, err - } - client, err := device.NewDriver(uixt.WithDriverPlugin(r.parser.plugin)) - if err != nil { - return nil, errors.Wrap(err, "init harmony driver failed") - } - uiClients[device.ConnectKey] = client } return parsedConfig, nil diff --git a/hrp/step_mobile_ui.go b/hrp/step_mobile_ui.go index 24401ec6..d6abd53b 100644 --- a/hrp/step_mobile_ui.go +++ b/hrp/step_mobile_ui.go @@ -14,32 +14,54 @@ import ( var uiClients = make(map[string]*uixt.DriverExt) // UI automation clients for iOS and Android, key is udid/serial -func initUIClient(serial, osType string) (client *uixt.DriverExt, err error) { - if uiClients == nil { - uiClients = make(map[string]*uixt.DriverExt) - } - - // get the first device - if serial == "" && len(uiClients) > 0 { - for _, v := range uiClients { - return v, nil - } - } - - // avoid duplicate init - if serial != "" { - if client, ok := uiClients[serial]; ok { - return client, nil +func initUIClient(serial, osType string, caseConfig *TConfig) (client *uixt.DriverExt, err error) { + // get cached driver + for key, driver := range uiClients { + // if serial is empty, return the first driver + if serial == "" { + return driver, nil + } + // or return the driver with the same serial + if key == serial { + return driver, nil } } + // init new driver var device uixt.IDevice - if osType == "ios" { - device, err = uixt.NewIOSDevice(uixt.WithUDID(serial)) - } else if osType == "harmony" { - device, err = uixt.NewHarmonyDevice(uixt.WithConnectKey(serial)) - } else { - device, err = uixt.NewAndroidDevice(uixt.WithSerialNumber(serial)) + switch strings.ToLower(osType) { + case "ios": + for _, ios := range caseConfig.IOS { + if serial == "" || ios.UDID == serial { + device, err = uixt.NewIOSDevice(ios.Options()...) + break + } + } + if device == nil { + device, err = uixt.NewIOSDevice(uixt.WithUDID(serial)) + } + case "harmony": + for _, harmony := range caseConfig.Harmony { + if serial == "" || harmony.ConnectKey == serial { + device, err = uixt.NewHarmonyDevice(harmony.Options()...) + break + } + } + if device == nil { + device, err = uixt.NewHarmonyDevice(uixt.WithConnectKey(serial)) + } + case "android": + for _, android := range caseConfig.Android { + if serial == "" || android.SerialNumber == serial { + device, err = uixt.NewAndroidDevice(android.Options()...) + break + } + } + if device == nil { + device, err = uixt.NewAndroidDevice(uixt.WithSerialNumber(serial)) + } + default: + return nil, errors.Errorf("unsupported os type: %s", osType) } if err != nil { return nil, errors.Wrapf(err, "init %s device failed", osType) @@ -55,10 +77,7 @@ func initUIClient(serial, osType string) (client *uixt.DriverExt, err error) { } // cache wda client - if uiClients == nil { - uiClients = make(map[string]*uixt.DriverExt) - } - uiClients[client.Device.UUID()] = client + uiClients[serial] = client return client, nil } @@ -73,29 +92,34 @@ type MobileUI struct { // StepMobile implements IStep interface. type StepMobile struct { StepConfig - stepObj *MobileUI Android *MobileUI `json:"android,omitempty" yaml:"android,omitempty"` Harmony *MobileUI `json:"harmony,omitempty" yaml:"harmony,omitempty"` IOS *MobileUI `json:"ios,omitempty" yaml:"ios,omitempty"` + + cache *MobileUI // used for caching } // uniform interface for all types of mobile systems func (s *StepMobile) obj() *MobileUI { - if s.stepObj != nil { - return s.stepObj + if s.cache != nil { + return s.cache } + if s.IOS != nil { - s.stepObj = s.IOS - s.stepObj.OSType = string(stepTypeIOS) - return s.stepObj + s.cache = s.IOS + s.cache.OSType = string(stepTypeIOS) + return s.cache } else if s.Harmony != nil { - s.stepObj = s.Harmony - s.stepObj.OSType = string(stepTypeHarmony) - return s.stepObj + s.cache = s.Harmony + s.cache.OSType = string(stepTypeHarmony) + return s.cache + } else if s.Android != nil { + s.cache = s.Android + s.cache.OSType = string(stepTypeAndroid) + return s.cache } - s.stepObj = s.Android - s.stepObj.OSType = string(stepTypeAndroid) - return s.stepObj + + panic("no mobile device config") } func (s *StepMobile) Serial(serial string) *StepMobile { @@ -651,8 +675,9 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err ContentSize: 0, } - // init wda/uia driver - uiDriver, err := initUIClient(mobileStep.Serial, mobileStep.OSType) + // init wda/uia/hdc driver + caseConfig := s.caseRunner.TestCase.Config.Get() + uiDriver, err := initUIClient(mobileStep.Serial, mobileStep.OSType, caseConfig) if err != nil { return }