diff --git a/cmd/adb/install.go b/cmd/adb/install.go index 342bab3b..b23ea718 100644 --- a/cmd/adb/install.go +++ b/cmd/adb/install.go @@ -9,6 +9,7 @@ import ( "github.com/httprunner/httprunner/v5/internal/sdk" "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) var ( @@ -35,7 +36,7 @@ var installCmd = &cobra.Command{ return err } - device, err := uixt.NewAndroidDevice(uixt.WithSerialNumber(serial)) + device, err := uixt.NewAndroidDevice(options.WithSerialNumber(serial)) if err != nil { fmt.Println(err) return err diff --git a/config.go b/config.go index a1e3b567..55c20a01 100644 --- a/config.go +++ b/config.go @@ -160,23 +160,23 @@ func (c *TConfig) SetHarmony(options ...uixt.HarmonyDeviceOption) *TConfig { return c } -func (c *TConfig) SetAndroid(options ...uixt.AndroidDeviceOption) *TConfig { - uiaOptions := &uixt.AndroidDevice{} - for _, option := range options { - option(uiaOptions) +func (c *TConfig) SetAndroid(opts ...options.AndroidDeviceOption) *TConfig { + uiaOptions := options.NewAndroidDeviceConfig(opts...) + device := &uixt.AndroidDevice{ + AndroidDeviceConfig: uiaOptions, } // each device can have its own settings if uiaOptions.SerialNumber != "" { - c.Android = append(c.Android, uiaOptions) + c.Android = append(c.Android, device) return c } // device UDID is not specified, settings will be shared if len(c.Android) == 0 { - c.Android = append(c.Android, uiaOptions) + c.Android = append(c.Android, device) } else { - c.Android[0] = uiaOptions + c.Android[0] = device } return c } diff --git a/examples/uitest/android_e2e_delay_test.go b/examples/uitest/android_e2e_delay_test.go index 5624a31c..cbd38009 100644 --- a/examples/uitest/android_e2e_delay_test.go +++ b/examples/uitest/android_e2e_delay_test.go @@ -5,6 +5,7 @@ import ( hrp "github.com/httprunner/httprunner/v5" "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) func TestAndroidDouyinE2E(t *testing.T) { @@ -14,7 +15,9 @@ func TestAndroidDouyinE2E(t *testing.T) { "device": "${ENV(SerialNumber)}", "ups": "${ENV(LIVEUPLIST)}", }). - SetAndroid(uixt.WithSerialNumber("$device"), uixt.WithAdbLogOn(true)), + SetAndroid( + options.WithSerialNumber("$device"), + options.WithAdbLogOn(true)), TestSteps: []hrp.IStep{ hrp.NewStep("启动抖音"). Android(). diff --git a/examples/uitest/bili/android/cli.go b/examples/uitest/bili/android/cli.go index adac973b..ec6d6029 100644 --- a/examples/uitest/bili/android/cli.go +++ b/examples/uitest/bili/android/cli.go @@ -7,6 +7,7 @@ import ( "time" "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) var ( @@ -28,7 +29,7 @@ func init() { } func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) { - device, _ := uixt.NewAndroidDevice(uixt.WithSerialNumber(serial)) + device, _ := uixt.NewAndroidDevice(options.WithSerialNumber(serial)) driver, err = device.NewDriver() if err != nil { return nil, err diff --git a/examples/uitest/demo_android_feed_swipe_test.go b/examples/uitest/demo_android_feed_swipe_test.go index 20c5b924..75fbd11e 100644 --- a/examples/uitest/demo_android_feed_swipe_test.go +++ b/examples/uitest/demo_android_feed_swipe_test.go @@ -7,6 +7,7 @@ import ( hrp "github.com/httprunner/httprunner/v5" "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) func TestAndroidDouyinFeedTest(t *testing.T) { @@ -15,7 +16,7 @@ func TestAndroidDouyinFeedTest(t *testing.T) { WithVariables(map[string]interface{}{ "device": "${ENV(SerialNumber)}", }). - SetAndroid(uixt.WithSerialNumber("$device")), + SetAndroid(options.WithSerialNumber("$device")), TestSteps: []hrp.IStep{ hrp.NewStep("启动抖音"). Android(). diff --git a/examples/uitest/demo_android_live_swipe_test.go b/examples/uitest/demo_android_live_swipe_test.go index 60738f99..55c0778b 100644 --- a/examples/uitest/demo_android_live_swipe_test.go +++ b/examples/uitest/demo_android_live_swipe_test.go @@ -7,6 +7,7 @@ import ( hrp "github.com/httprunner/httprunner/v5" "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) func TestAndroidLiveSwipeTest(t *testing.T) { @@ -15,7 +16,7 @@ func TestAndroidLiveSwipeTest(t *testing.T) { WithVariables(map[string]interface{}{ "device": "${ENV(SerialNumber)}", }). - SetAndroid(uixt.WithSerialNumber("$device")), + SetAndroid(options.WithSerialNumber("$device")), TestSteps: []hrp.IStep{ hrp.NewStep("启动抖音"). Android(). diff --git a/examples/uitest/demo_harmony_test.go b/examples/uitest/demo_harmony_test.go index 9925d238..5d4ca076 100644 --- a/examples/uitest/demo_harmony_test.go +++ b/examples/uitest/demo_harmony_test.go @@ -6,7 +6,7 @@ import ( "testing" hrp "github.com/httprunner/httprunner/v5" - "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) func TestHamonyDouyinFeedTest(t *testing.T) { @@ -16,7 +16,7 @@ func TestHamonyDouyinFeedTest(t *testing.T) { "device": "a38c2c5c", "query": "${ENV(query)}", }). - SetAndroid(uixt.WithSerialNumber("$device")), + SetAndroid(options.WithSerialNumber("$device")), TestSteps: []hrp.IStep{ hrp.NewStep("启动抖音"). Android(). diff --git a/examples/uitest/expert_test.go b/examples/uitest/expert_test.go index 41e12bb1..f8e3ae5a 100644 --- a/examples/uitest/expert_test.go +++ b/examples/uitest/expert_test.go @@ -18,9 +18,9 @@ func TestAndroidExpertTest(t *testing.T) { "app_name": "抖音", }). SetAndroid( - uixt.WithSerialNumber("$device"), - uixt.WithAdbLogOn(true), - uixt.WithUIA2(true), + options.WithSerialNumber("$device"), + options.WithAdbLogOn(true), + options.WithUIA2(true), ), TestSteps: []hrp.IStep{ // 温启动 diff --git a/examples/worldcup/main.go b/examples/worldcup/main.go index c346bb43..8a036c80 100644 --- a/examples/worldcup/main.go +++ b/examples/worldcup/main.go @@ -51,7 +51,7 @@ func initIOSDevice(uuid string) uixt.IDevice { } func initAndroidDevice(uuid string) uixt.IDevice { - device, err := uixt.NewAndroidDevice(uixt.WithSerialNumber(uuid)) + device, err := uixt.NewAndroidDevice(options.WithSerialNumber(uuid)) if err != nil { log.Fatal().Err(err).Msg("failed to init android device") } diff --git a/pkg/uixt/ai_vedem_test.go b/pkg/uixt/ai_vedem_test.go index df0eaee5..fb100a56 100644 --- a/pkg/uixt/ai_vedem_test.go +++ b/pkg/uixt/ai_vedem_test.go @@ -7,6 +7,8 @@ import ( "fmt" "os" "testing" + + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) func checkOCR(buff *bytes.Buffer) error { @@ -53,7 +55,7 @@ func TestOCRWithLocalFile(t *testing.T) { func TestTapUIWithScreenshot(t *testing.T) { serialNumber := os.Getenv("SERIAL_NUMBER") - device, _ := NewAndroidDevice(WithSerialNumber(serialNumber)) + device, _ := NewAndroidDevice(options.WithSerialNumber(serialNumber)) driver, err := device.NewDriver() if err != nil { t.Fatal(err) diff --git a/pkg/uixt/android_device.go b/pkg/uixt/android_device.go index ffad16c7..8a769379 100644 --- a/pkg/uixt/android_device.go +++ b/pkg/uixt/android_device.go @@ -24,6 +24,7 @@ import ( "github.com/httprunner/httprunner/v5/internal/config" "github.com/httprunner/httprunner/v5/internal/json" "github.com/httprunner/httprunner/v5/pkg/gadb" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" ) var ( @@ -48,58 +49,20 @@ var evalite embed.FS const forwardToPrefix = "forward-to-" -type AndroidDeviceOption func(*AndroidDevice) - -func WithSerialNumber(serial string) AndroidDeviceOption { - return func(device *AndroidDevice) { - device.SerialNumber = serial - } -} - -func WithUIA2(uia2On bool) AndroidDeviceOption { - return func(device *AndroidDevice) { - device.UIA2 = uia2On - } -} - -func WithStub(stubOn bool) AndroidDeviceOption { - return func(device *AndroidDevice) { - device.STUB = stubOn - } -} - -func WithUIA2IP(ip string) AndroidDeviceOption { - return func(device *AndroidDevice) { - device.UIA2IP = ip - } -} - -func WithUIA2Port(port int) AndroidDeviceOption { - return func(device *AndroidDevice) { - device.UIA2Port = port - } -} - -func WithAdbLogOn(logOn bool) AndroidDeviceOption { - return func(device *AndroidDevice) { - device.LogOn = logOn - } -} - -func NewAndroidDevice(options ...AndroidDeviceOption) (device *AndroidDevice, err error) { - device = &AndroidDevice{ +func NewAndroidDevice(opts ...options.AndroidDeviceOption) (device *AndroidDevice, err error) { + androidOptions := &options.AndroidDeviceConfig{ UIA2IP: UIA2ServerHost, UIA2Port: UIA2ServerPort, } - for _, option := range options { - option(device) + for _, option := range opts { + option(androidOptions) } - deviceList, err := GetAndroidDevices(device.SerialNumber) + deviceList, err := GetAndroidDevices(androidOptions.SerialNumber) if err != nil { return nil, errors.Wrap(code.DeviceConnectionError, err.Error()) } - if device.SerialNumber == "" && len(deviceList) > 1 { + if androidOptions.SerialNumber == "" && len(deviceList) > 1 { return nil, errors.Wrap(code.DeviceConnectionError, "more than one device connected, please specify the serial") } @@ -113,8 +76,12 @@ func NewAndroidDevice(options ...AndroidDeviceOption) (device *AndroidDevice, er Msg("android SerialNumber is not specified, select the first one") } - device.d = dev - device.logcat = NewAdbLogcat(device.SerialNumber) + device = &AndroidDevice{ + AndroidDeviceConfig: androidOptions, + d: dev, + logcat: NewAdbLogcat(device.SerialNumber), + } + evalToolRaw, err := evalite.ReadFile("evalite") if err != nil { return nil, errors.Wrap(code.LoadFileError, err.Error()) @@ -161,33 +128,9 @@ func GetAndroidDevices(serial ...string) (devices []*gadb.Device, err error) { } type AndroidDevice struct { - d *gadb.Device - logcat *AdbLogcat - SerialNumber string `json:"serial,omitempty" yaml:"serial,omitempty"` - STUB bool `json:"stub,omitempty" yaml:"stub,omitempty"` // use stub - UIA2 bool `json:"uia2,omitempty" yaml:"uia2,omitempty"` // use uiautomator2 - UIA2IP string `json:"uia2_ip,omitempty" yaml:"uia2_ip,omitempty"` // uiautomator2 server ip - UIA2Port int `json:"uia2_port,omitempty" yaml:"uia2_port,omitempty"` // uiautomator2 server port - LogOn bool `json:"log_on,omitempty" yaml:"log_on,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 + *options.AndroidDeviceConfig + d *gadb.Device + logcat *AdbLogcat } func (dev *AndroidDevice) Init() error { diff --git a/pkg/uixt/options/android.go b/pkg/uixt/options/android.go index 0684d059..e65b91bd 100644 --- a/pkg/uixt/options/android.go +++ b/pkg/uixt/options/android.go @@ -1 +1,75 @@ package options + +type AndroidDeviceConfig struct { + SerialNumber string `json:"serial,omitempty" yaml:"serial,omitempty"` + STUB bool `json:"stub,omitempty" yaml:"stub,omitempty"` // use stub + UIA2 bool `json:"uia2,omitempty" yaml:"uia2,omitempty"` // use uiautomator2 + UIA2IP string `json:"uia2_ip,omitempty" yaml:"uia2_ip,omitempty"` // uiautomator2 server ip + UIA2Port int `json:"uia2_port,omitempty" yaml:"uia2_port,omitempty"` // uiautomator2 server port + LogOn bool `json:"log_on,omitempty" yaml:"log_on,omitempty"` +} + +func (dev *AndroidDeviceConfig) 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 NewAndroidDeviceConfig(opts ...AndroidDeviceOption) *AndroidDeviceConfig { + config := &AndroidDeviceConfig{} + for _, opt := range opts { + opt(config) + } + return config +} + +type AndroidDeviceOption func(*AndroidDeviceConfig) + +func WithSerialNumber(serial string) AndroidDeviceOption { + return func(device *AndroidDeviceConfig) { + device.SerialNumber = serial + } +} + +func WithUIA2(uia2On bool) AndroidDeviceOption { + return func(device *AndroidDeviceConfig) { + device.UIA2 = uia2On + } +} + +func WithStub(stubOn bool) AndroidDeviceOption { + return func(device *AndroidDeviceConfig) { + device.STUB = stubOn + } +} + +func WithUIA2IP(ip string) AndroidDeviceOption { + return func(device *AndroidDeviceConfig) { + device.UIA2IP = ip + } +} + +func WithUIA2Port(port int) AndroidDeviceOption { + return func(device *AndroidDeviceConfig) { + device.UIA2Port = port + } +} + +func WithAdbLogOn(logOn bool) AndroidDeviceOption { + return func(device *AndroidDeviceConfig) { + device.LogOn = logOn + } +} diff --git a/server/context.go b/server/context.go index 5bf60a65..53a7dd6d 100644 --- a/server/context.go +++ b/server/context.go @@ -8,6 +8,7 @@ import ( "github.com/gin-gonic/gin" "github.com/httprunner/httprunner/v5/code" "github.com/httprunner/httprunner/v5/pkg/uixt" + "github.com/httprunner/httprunner/v5/pkg/uixt/options" "github.com/rs/zerolog/log" ) @@ -35,7 +36,9 @@ func handleDeviceContext() gin.HandlerFunc { switch strings.ToLower(platform) { case "android": - device, err := uixt.NewAndroidDevice(uixt.WithSerialNumber(serial), uixt.WithStub(true)) + device, err := uixt.NewAndroidDevice( + options.WithSerialNumber(serial), + options.WithStub(true)) if err != nil { log.Error().Err(err).Str("platform", platform).Str("serial", serial). Msg("device not found") diff --git a/step_request.go b/step_request.go index 3d40629b..8cbf45aa 100644 --- a/step_request.go +++ b/step_request.go @@ -760,11 +760,8 @@ func (s *StepRequest) MobileUI() *StepMobile { } // Android creates a new android step session -func (s *StepRequest) Android(options ...uixt.AndroidDeviceOption) *StepMobile { - androidOptions := &uixt.AndroidDevice{} - for _, option := range options { - option(androidOptions) - } +func (s *StepRequest) Android(opts ...options.AndroidDeviceOption) *StepMobile { + androidOptions := options.NewAndroidDeviceConfig(opts...) return &StepMobile{ StepConfig: s.StepConfig, Android: &MobileUI{