feat: create scaffold for mobile UI test

This commit is contained in:
debugtalk
2022-07-26 17:39:48 +08:00
parent 7a08760eaf
commit ea311c1882
5 changed files with 444 additions and 0 deletions

View File

@@ -10,8 +10,32 @@ const (
stepTypeRendezvous StepType = "rendezvous"
stepTypeThinkTime StepType = "thinktime"
stepTypeWebSocket StepType = "websocket"
stepTypeAndroid StepType = "android"
stepTypeIOS StepType = "ios"
)
type MobileMethod string
const (
appInstall MobileMethod = "install"
appStart MobileMethod = "app_start"
cameraStart MobileMethod = "camera_start"
cameraStop MobileMethod = "camera_stop"
recordStart MobileMethod = "record_start"
recordStop MobileMethod = "record_stop"
uiClick MobileMethod = "click"
uiDoubleClick MobileMethod = "double_click"
uiLongClick MobileMethod = "long_click"
uiSwipe MobileMethod = "swipe"
uiInput MobileMethod = "input"
appClick MobileMethod = "app_click"
)
type MobileAction struct {
Method MobileMethod `json:"method" yaml:"method"`
Params interface{} `json:"params,omitempty" yaml:"params,omitempty"`
}
type StepResult struct {
Name string `json:"name" yaml:"name"` // step name
StepType StepType `json:"step_type" yaml:"step_type"` // step type, testcase/request/transaction/rendezvous
@@ -35,6 +59,8 @@ type TStep struct {
Rendezvous *Rendezvous `json:"rendezvous,omitempty" yaml:"rendezvous,omitempty"`
ThinkTime *ThinkTime `json:"think_time,omitempty" yaml:"think_time,omitempty"`
WebSocket *WebSocketAction `json:"websocket,omitempty" yaml:"websocket,omitempty"`
Android *AndroidAction `json:"android,omitempty" yaml:"android,omitempty"`
IOS *IOSAction `json:"ios,omitempty" yaml:"ios,omitempty"`
Variables map[string]interface{} `json:"variables,omitempty" yaml:"variables,omitempty"`
SetupHooks []string `json:"setup_hooks,omitempty" yaml:"setup_hooks,omitempty"`
TeardownHooks []string `json:"teardown_hooks,omitempty" yaml:"teardown_hooks,omitempty"`

199
hrp/step_android_ui.go Normal file
View File

@@ -0,0 +1,199 @@
package hrp
type AndroidAction struct {
MobileAction
Serial string `json:"serial,omitempty" yaml:"serial,omitempty"`
Actions []MobileAction `json:"actions,omitempty" yaml:"actions,omitempty"`
}
// StepAndroid implements IStep interface.
type StepAndroid struct {
step *TStep
}
func (s *StepAndroid) Serial(serial string) *StepAndroid {
s.step.Android.Serial = serial
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) InstallApp(path string) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: appInstall,
Params: path,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) StartAppByIntent(activity string) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: appStart,
Params: activity,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) StartCamera() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: cameraStart,
Params: nil,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) StopCamera() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: cameraStop,
Params: nil,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) StartRecording() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: recordStart,
Params: nil,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) StopRecording() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: recordStop,
Params: nil,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) Click(params interface{}) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiClick,
Params: params,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) DoubleClick(params interface{}) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiDoubleClick,
Params: params,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) LongClick(params interface{}) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiLongClick,
Params: params,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) Swipe(sx, sy, ex, ey int) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiSwipe,
Params: []int{sx, sy, ex, ey},
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) SwipeUp() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiSwipe,
Params: "up",
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) SwipeDown() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiSwipe,
Params: "down",
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) SwipeLeft() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiSwipe,
Params: "left",
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) SwipeRight() *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiSwipe,
Params: "right",
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) Input(text string) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: uiInput,
Params: text,
})
return &StepAndroid{step: s.step}
}
func (s *StepAndroid) StartAppByClick(name string) *StepAndroid {
s.step.Android.Actions = append(s.step.Android.Actions, MobileAction{
Method: appClick,
Params: name,
})
return &StepAndroid{step: s.step}
}
// Validate switches to step validation.
func (s *StepAndroid) Validate() *StepAndroidValidation {
return &StepAndroidValidation{
step: s.step,
}
}
func (s *StepAndroid) Name() string {
return s.step.Name
}
func (s *StepAndroid) Type() StepType {
return stepTypeAndroid
}
func (s *StepAndroid) Struct() *TStep {
return s.step
}
func (s *StepAndroid) Run(r *SessionRunner) (*StepResult, error) {
return runStepAndroid(r, s.step)
}
// StepAndroidValidation implements IStep interface.
type StepAndroidValidation struct {
step *TStep
}
func (s *StepAndroidValidation) Name() string {
return s.step.Name
}
func (s *StepAndroidValidation) Type() StepType {
return stepTypeAndroid
}
func (s *StepAndroidValidation) Struct() *TStep {
return s.step
}
func (s *StepAndroidValidation) Run(r *SessionRunner) (*StepResult, error) {
return runStepAndroid(r, s.step)
}
func runStepAndroid(r *SessionRunner, step *TStep) (stepResult *StepResult, err error) {
stepResult = &StepResult{
Name: step.Name,
StepType: stepTypeAndroid,
Success: false,
ContentSize: 0,
}
return stepResult, nil
}

159
hrp/step_ios_ui.go Normal file
View File

@@ -0,0 +1,159 @@
package hrp
type IOSAction struct {
MobileAction
UDID string `json:"udid,omitempty" yaml:"udid,omitempty"`
Actions []MobileAction `json:"actions,omitempty" yaml:"actions,omitempty"`
}
// StepIOS implements IStep interface.
type StepIOS struct {
step *TStep
}
func (s *StepIOS) UDID(udid string) *StepIOS {
s.step.IOS.UDID = udid
return &StepIOS{step: s.step}
}
func (s *StepIOS) InstallApp(path string) *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: appInstall,
Params: path,
})
return s
}
func (s *StepIOS) Click(params interface{}) *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiClick,
Params: params,
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) DoubleClick(params interface{}) *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiDoubleClick,
Params: params,
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) LongClick(params interface{}) *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiLongClick,
Params: params,
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) Swipe(sx, sy, ex, ey int) *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiSwipe,
Params: []int{sx, sy, ex, ey},
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) SwipeUp() *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiSwipe,
Params: "up",
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) SwipeDown() *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiSwipe,
Params: "down",
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) SwipeLeft() *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiSwipe,
Params: "left",
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) SwipeRight() *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiSwipe,
Params: "right",
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) Input(text string) *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: uiInput,
Params: text,
})
return &StepIOS{step: s.step}
}
func (s *StepIOS) StartAppByClick(name string) *StepIOS {
s.step.IOS.Actions = append(s.step.IOS.Actions, MobileAction{
Method: appClick,
Params: name,
})
return &StepIOS{step: s.step}
}
// Validate switches to step validation.
func (s *StepIOS) Validate() *StepIOSValidation {
return &StepIOSValidation{
step: s.step,
}
}
func (s *StepIOS) Name() string {
return s.step.Name
}
func (s *StepIOS) Type() StepType {
return stepTypeAndroid
}
func (s *StepIOS) Struct() *TStep {
return s.step
}
func (s *StepIOS) Run(r *SessionRunner) (*StepResult, error) {
return runStepIOS(r, s.step)
}
// StepIOSValidation implements IStep interface.
type StepIOSValidation struct {
step *TStep
}
func (s *StepIOSValidation) Name() string {
return s.step.Name
}
func (s *StepIOSValidation) Type() StepType {
return stepTypeAndroid
}
func (s *StepIOSValidation) Struct() *TStep {
return s.step
}
func (s *StepIOSValidation) Run(r *SessionRunner) (*StepResult, error) {
return runStepIOS(r, s.step)
}
func runStepIOS(r *SessionRunner, step *TStep) (stepResult *StepResult, err error) {
stepResult = &StepResult{
Name: step.Name,
StepType: stepTypeAndroid,
Success: false,
ContentSize: 0,
}
return stepResult, nil
}

View File

@@ -759,6 +759,22 @@ func (s *StepRequest) WebSocket() *StepWebSocket {
}
}
// Android creates a new android action
func (s *StepRequest) Android() *StepAndroid {
s.step.Android = &AndroidAction{}
return &StepAndroid{
step: s.step,
}
}
// IOS creates a new ios action
func (s *StepRequest) IOS() *StepIOS {
s.step.IOS = &IOSAction{}
return &StepIOS{
step: s.step,
}
}
// StepRequestWithOptionalArgs implements IStep interface.
type StepRequestWithOptionalArgs struct {
step *TStep

44
hrp/step_ui_test.go Normal file
View File

@@ -0,0 +1,44 @@
package hrp
import (
"fmt"
"testing"
)
func TestAndroidAction(t *testing.T) {
testCase := &TestCase{
Config: NewConfig("android ui action"),
TestSteps: []IStep{
NewStep("launch douyin").
Android().Serial("xxx").Click("抖音"),
NewStep("swipe up and down").
Android().Serial("xxx").SwipeUp().SwipeUp().SwipeDown(),
},
}
tCase := testCase.ToTCase()
fmt.Println(tCase)
err := NewRunner(t).Run(testCase)
if err != nil {
t.Fatal(err)
}
}
func TestIOSAction(t *testing.T) {
testCase := &TestCase{
Config: NewConfig("ios ui action"),
TestSteps: []IStep{
NewStep("launch douyin").
IOS().UDID("xxx").Click("抖音"),
NewStep("swipe up and down").
IOS().UDID("xxx").SwipeUp().SwipeUp().SwipeDown(),
},
}
tCase := testCase.ToTCase()
fmt.Println(tCase)
err := NewRunner(t).Run(testCase)
if err != nil {
t.Fatal(err)
}
}