diff --git a/hrp/internal/version/VERSION b/hrp/internal/version/VERSION index e30021b2..4892ef0a 100644 --- a/hrp/internal/version/VERSION +++ b/hrp/internal/version/VERSION @@ -1 +1 @@ -v5.0.0+2411101049 +v5.0.0+2411102027 diff --git a/hrp/runner.go b/hrp/runner.go index 748ee1e8..9cc3624b 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -26,6 +26,7 @@ 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. @@ -233,7 +234,7 @@ func (r *HRPRunner) Run(testcases ...ITestCase) (err error) { // release UI driver session defer func() { - for _, client := range uiClients { + for _, client := range caseRunner.uixtDrivers { client.Driver.DeleteSession() } }() @@ -277,9 +278,10 @@ func (r *HRPRunner) Run(testcases ...ITestCase) (err error) { // each testcase has its own case runner func (r *HRPRunner) NewCaseRunner(testcase TestCase) (*CaseRunner, error) { caseRunner := &CaseRunner{ - TestCase: testcase, - hrpRunner: r, - parser: newParser(), + TestCase: testcase, + hrpRunner: r, + parser: newParser(), + uixtDrivers: make(map[string]*uixt.DriverExt), } config := testcase.Config.Get() @@ -335,6 +337,9 @@ type CaseRunner struct { parser *Parser // each CaseRunner init its own Parser parametersIterator *ParametersIterator + + // UI automation clients for iOS and Android, key is udid/serial + uixtDrivers map[string]*uixt.DriverExt } // parseConfig parses testcase config, stores to parsedConfig. @@ -522,7 +527,7 @@ func (r *SessionRunner) Start(givenVars map[string]interface{}) (summary *TestCa summary.InOut.ConfigVars = config.Variables // TODO: move to mobile ui step - for uuid, client := range uiClients { + for uuid, client := range r.caseRunner.uixtDrivers { // add WDA/UIA logs to summary logs := map[string]interface{}{ "uuid": uuid, diff --git a/hrp/step_mobile_ui.go b/hrp/step_mobile_ui.go index d6b747f2..507c0161 100644 --- a/hrp/step_mobile_ui.go +++ b/hrp/step_mobile_ui.go @@ -13,11 +13,9 @@ import ( "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" ) -var uiClients = make(map[string]*uixt.DriverExt) // UI automation clients for iOS and Android, key is udid/serial - -func initUIClient(serial, osType string, caseConfig *TConfig) (client *uixt.DriverExt, err error) { +func (r *SessionRunner) GetUIXTDriver(serial, osType string) (driver *uixt.DriverExt, err error) { // get cached driver - for key, driver := range uiClients { + for key, driver := range r.caseRunner.uixtDrivers { // if serial is empty, return the first driver if serial == "" { return driver, nil @@ -28,6 +26,7 @@ func initUIClient(serial, osType string, caseConfig *TConfig) (client *uixt.Driv } } + caseConfig := r.caseRunner.TestCase.Config.Get() // init new driver var device uixt.IDevice switch strings.ToLower(osType) { @@ -72,15 +71,15 @@ func initUIClient(serial, osType string, caseConfig *TConfig) (client *uixt.Driv return nil, err } - client, err = device.NewDriver() + driver, err = device.NewDriver() if err != nil { return nil, err } - // cache wda client - uiClients[serial] = client + // cache driver + r.caseRunner.uixtDrivers[serial] = driver - return client, nil + return driver, nil } type MobileUI struct { @@ -656,8 +655,7 @@ func runStepMobileUI(s *SessionRunner, step IStep) (stepResult *StepResult, err }) // init wda/uia/hdc driver - caseConfig := s.caseRunner.TestCase.Config.Get() - uiDriver, err := initUIClient(mobileStep.Serial, mobileStep.OSType, caseConfig) + uiDriver, err := s.GetUIXTDriver(mobileStep.Serial, mobileStep.OSType) if err != nil { return } diff --git a/hrp/step_request.go b/hrp/step_request.go index 2d5034da..51fa3319 100644 --- a/hrp/step_request.go +++ b/hrp/step_request.go @@ -24,6 +24,7 @@ import ( "github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/json" "github.com/httprunner/httprunner/v4/hrp/pkg/httpstat" + "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" ) type HTTPMethod string @@ -748,31 +749,52 @@ func (s *StepRequest) WebSocket() *StepWebSocket { } } -// Android creates a new android action -func (s *StepRequest) Android() *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) + } return &StepMobile{ StepConfig: s.StepConfig, - Android: &MobileUI{}, + Android: &MobileUI{ + OSType: string(stepTypeAndroid), + Serial: androidOptions.SerialNumber, + }, } } -// IOS creates a new ios action -func (s *StepRequest) IOS() *StepMobile { +// IOS creates a new ios step session +func (s *StepRequest) IOS(options ...uixt.IOSDeviceOption) *StepMobile { + iosOptions := &uixt.IOSDevice{} + for _, option := range options { + option(iosOptions) + } return &StepMobile{ StepConfig: s.StepConfig, - IOS: &MobileUI{}, + IOS: &MobileUI{ + OSType: string(stepTypeIOS), + Serial: iosOptions.UDID, + }, } } -// Harmony creates a new harmony action -func (s *StepRequest) Harmony() *StepMobile { +// Harmony creates a new harmony step session +func (s *StepRequest) Harmony(options ...uixt.HarmonyDeviceOption) *StepMobile { + harmonyOptions := &uixt.HarmonyDevice{} + for _, option := range options { + option(harmonyOptions) + } return &StepMobile{ StepConfig: s.StepConfig, - Harmony: &MobileUI{}, + Harmony: &MobileUI{ + OSType: string(stepTypeHarmony), + Serial: harmonyOptions.ConnectKey, + }, } } -// Shell creates a new shell action +// Shell creates a new shell step session func (s *StepRequest) Shell(content string) *StepShell { return &StepShell{ StepConfig: s.StepConfig,