mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-12 02:21:29 +08:00
feat: create scaffold for mobile UI test
This commit is contained in:
26
hrp/step.go
26
hrp/step.go
@@ -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
199
hrp/step_android_ui.go
Normal 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
159
hrp/step_ios_ui.go
Normal 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
|
||||
}
|
||||
@@ -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
44
hrp/step_ui_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user