mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-20 07:40:32 +08:00
fix: tap x,y positions
This commit is contained in:
112
examples/uitest/wda_log_data.json
Normal file
112
examples/uitest/wda_log_data.json
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"name": "验证 WDA 打点数据准确性",
|
||||||
|
"variables": {
|
||||||
|
"app_name": "抖音"
|
||||||
|
},
|
||||||
|
"ios": [
|
||||||
|
{
|
||||||
|
"port": 8700,
|
||||||
|
"mjpeg_port": 8800,
|
||||||
|
"log_on": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"teststeps": [
|
||||||
|
{
|
||||||
|
"name": "启动抖音",
|
||||||
|
"ios": {
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"method": "home"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "app_terminate",
|
||||||
|
"params": "com.ss.iphone.ugc.Aweme"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "swipe_to_tap_app",
|
||||||
|
"params": "$app_name",
|
||||||
|
"identifier": "启动抖音",
|
||||||
|
"max_retry_times": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "sleep",
|
||||||
|
"params": 5
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"validate": [
|
||||||
|
{
|
||||||
|
"check": "ui_ocr",
|
||||||
|
"assert": "exists",
|
||||||
|
"expect": "推荐",
|
||||||
|
"msg": "抖音启动失败,「推荐」不存在"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "处理青少年弹窗",
|
||||||
|
"ios": {
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"method": "tap_ocr",
|
||||||
|
"params": "我知道了",
|
||||||
|
"ignore_NotFoundError": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "向上滑动 2 次",
|
||||||
|
"ios": {
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"method": "swipe",
|
||||||
|
"params": "up",
|
||||||
|
"identifier": "第 1 次上划"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "sleep",
|
||||||
|
"params": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "swipe",
|
||||||
|
"params": "up",
|
||||||
|
"identifier": "第 2 次上划"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "sleep",
|
||||||
|
"params": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "swipe",
|
||||||
|
"params": "up",
|
||||||
|
"identifier": "第 3 次上划"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "sleep",
|
||||||
|
"params": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "tap_xy",
|
||||||
|
"params": [
|
||||||
|
0.9,
|
||||||
|
0.1
|
||||||
|
],
|
||||||
|
"identifier": "点击进入搜索框"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "sleep",
|
||||||
|
"params": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "input",
|
||||||
|
"params": "httprunner",
|
||||||
|
"identifier": "输入搜索关键词"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
48
examples/uitest/wda_log_test.go
Normal file
48
examples/uitest/wda_log_test.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
//go:build localtest
|
||||||
|
|
||||||
|
package uitest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWDALog(t *testing.T) {
|
||||||
|
testCase := &hrp.TestCase{
|
||||||
|
Config: hrp.NewConfig("验证 WDA 打点数据准确性").
|
||||||
|
WithVariables(map[string]interface{}{
|
||||||
|
"app_name": "抖音",
|
||||||
|
}).
|
||||||
|
SetIOS(hrp.WithLogOn(true), hrp.WithPort(8700), hrp.WithMjpegPort(8800)),
|
||||||
|
TestSteps: []hrp.IStep{
|
||||||
|
hrp.NewStep("启动抖音").
|
||||||
|
IOS().
|
||||||
|
Home().
|
||||||
|
AppTerminate("com.ss.iphone.ugc.Aweme"). // 关闭已运行的抖音
|
||||||
|
SwipeToTapApp("$app_name", hrp.WithMaxRetryTimes(5), hrp.WithIdentifier("启动抖音")).Sleep(5).
|
||||||
|
Validate().
|
||||||
|
AssertOCRExists("推荐", "抖音启动失败,「推荐」不存在"),
|
||||||
|
hrp.NewStep("处理青少年弹窗").
|
||||||
|
IOS().
|
||||||
|
TapByOCR("我知道了", hrp.WithIgnoreNotFoundError(true)),
|
||||||
|
hrp.NewStep("向上滑动 2 次").
|
||||||
|
IOS().
|
||||||
|
SwipeUp(hrp.WithIdentifier("第 1 次上划")).Sleep(2).
|
||||||
|
SwipeUp(hrp.WithIdentifier("第 2 次上划")).Sleep(2).
|
||||||
|
SwipeUp(hrp.WithIdentifier("第 3 次上划")).Sleep(2).
|
||||||
|
TapXY(0.9, 0.1, hrp.WithIdentifier("点击进入搜索框")).Sleep(2).
|
||||||
|
Input("httprunner", hrp.WithIdentifier("输入搜索关键词")),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := testCase.Dump2JSON("wda_log_data.json"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
runner := hrp.NewRunner(t).SetSaveTests(true)
|
||||||
|
err := runner.Run(testCase)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -391,21 +392,25 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
case ACTION_Home:
|
case ACTION_Home:
|
||||||
return dExt.Driver.Homescreen()
|
return dExt.Driver.Homescreen()
|
||||||
case ACTION_TapXY:
|
case ACTION_TapXY:
|
||||||
if location, ok := action.Params.([]float64); ok {
|
if location, ok := action.Params.([]interface{}); ok {
|
||||||
// relative x,y of window size: [0.5, 0.5]
|
// relative x,y of window size: [0.5, 0.5]
|
||||||
if len(location) != 2 {
|
if len(location) != 2 {
|
||||||
return fmt.Errorf("invalid tap location params: %v", location)
|
return fmt.Errorf("invalid tap location params: %v", location)
|
||||||
}
|
}
|
||||||
return dExt.TapXY(location[0], location[1], action.Identifier)
|
x, _ := location[0].(float64)
|
||||||
|
y, _ := location[1].(float64)
|
||||||
|
return dExt.TapXY(x, y, action.Identifier)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid %s params: %v", ACTION_TapXY, action.Params)
|
return fmt.Errorf("invalid %s params: %v", ACTION_TapXY, action.Params)
|
||||||
case ACTION_TapAbsXY:
|
case ACTION_TapAbsXY:
|
||||||
if location, ok := action.Params.([]float64); ok {
|
if location, ok := action.Params.([]interface{}); ok {
|
||||||
// absolute coordinates x,y of window size: [100, 300]
|
// absolute coordinates x,y of window size: [100, 300]
|
||||||
if len(location) != 2 {
|
if len(location) != 2 {
|
||||||
return fmt.Errorf("invalid tap location params: %v", location)
|
return fmt.Errorf("invalid tap location params: %v", location)
|
||||||
}
|
}
|
||||||
return dExt.TapAbsXY(location[0], location[1], action.Identifier)
|
x, _ := location[0].(float64)
|
||||||
|
y, _ := location[1].(float64)
|
||||||
|
return dExt.TapAbsXY(x, y, action.Identifier)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid %s params: %v", ACTION_TapAbsXY, action.Params)
|
return fmt.Errorf("invalid %s params: %v", ACTION_TapAbsXY, action.Params)
|
||||||
case ACTION_Tap:
|
case ACTION_Tap:
|
||||||
@@ -424,12 +429,14 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("invalid %s params: %v", ACTION_TapByCV, action.Params)
|
return fmt.Errorf("invalid %s params: %v", ACTION_TapByCV, action.Params)
|
||||||
case ACTION_DoubleTapXY:
|
case ACTION_DoubleTapXY:
|
||||||
if location, ok := action.Params.([]float64); ok {
|
if location, ok := action.Params.([]interface{}); ok {
|
||||||
// relative x,y of window size: [0.5, 0.5]
|
// relative x,y of window size: [0.5, 0.5]
|
||||||
if len(location) != 2 {
|
if len(location) != 2 {
|
||||||
return fmt.Errorf("invalid tap location params: %v", location)
|
return fmt.Errorf("invalid tap location params: %v", location)
|
||||||
}
|
}
|
||||||
return dExt.DoubleTapXY(location[0], location[1])
|
x, _ := location[0].(float64)
|
||||||
|
y, _ := location[1].(float64)
|
||||||
|
return dExt.DoubleTapXY(x, y)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid %s params: %v", ACTION_DoubleTapXY, action.Params)
|
return fmt.Errorf("invalid %s params: %v", ACTION_DoubleTapXY, action.Params)
|
||||||
case ACTION_DoubleTap:
|
case ACTION_DoubleTap:
|
||||||
@@ -438,13 +445,16 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("invalid %s params: %v", ACTION_DoubleTap, action.Params)
|
return fmt.Errorf("invalid %s params: %v", ACTION_DoubleTap, action.Params)
|
||||||
case ACTION_Swipe:
|
case ACTION_Swipe:
|
||||||
if positions, ok := action.Params.([]float64); ok {
|
if positions, ok := action.Params.([]interface{}); ok {
|
||||||
// relative fromX, fromY, toX, toY of window size: [0.5, 0.9, 0.5, 0.1]
|
// relative fromX, fromY, toX, toY of window size: [0.5, 0.9, 0.5, 0.1]
|
||||||
if len(positions) != 4 {
|
if len(positions) != 4 {
|
||||||
return fmt.Errorf("invalid swipe params [fromX, fromY, toX, toY]: %v", positions)
|
return fmt.Errorf("invalid swipe params [fromX, fromY, toX, toY]: %v", positions)
|
||||||
}
|
}
|
||||||
return dExt.SwipeRelative(
|
fromX, _ := positions[0].(float64)
|
||||||
positions[0], positions[1], positions[2], positions[3], action.Identifier)
|
fromY, _ := positions[1].(float64)
|
||||||
|
toX, _ := positions[2].(float64)
|
||||||
|
toY, _ := positions[3].(float64)
|
||||||
|
return dExt.SwipeRelative(fromX, fromY, toX, toY, action.Identifier)
|
||||||
}
|
}
|
||||||
if direction, ok := action.Params.(string); ok {
|
if direction, ok := action.Params.(string); ok {
|
||||||
return dExt.SwipeTo(direction, action.Identifier)
|
return dExt.SwipeTo(direction, action.Identifier)
|
||||||
@@ -455,6 +465,13 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
// append \n to send text with enter
|
// append \n to send text with enter
|
||||||
// send \b\b\b to delete 3 chars
|
// send \b\b\b to delete 3 chars
|
||||||
param := fmt.Sprintf("%v", action.Params)
|
param := fmt.Sprintf("%v", action.Params)
|
||||||
|
if action.Identifier != "" {
|
||||||
|
option := WithCustomOption("log", map[string]interface{}{
|
||||||
|
"enable": true,
|
||||||
|
"data": action.Identifier,
|
||||||
|
})
|
||||||
|
return dExt.Driver.SendKeys(param, option)
|
||||||
|
}
|
||||||
return dExt.Driver.SendKeys(param)
|
return dExt.Driver.SendKeys(param)
|
||||||
case CtlSleep:
|
case CtlSleep:
|
||||||
if param, ok := action.Params.(json.Number); ok {
|
if param, ok := action.Params.(json.Number); ok {
|
||||||
@@ -529,3 +546,13 @@ func (dExt *DriverExt) DoValidation(check, assert, expected string, message ...s
|
|||||||
Msg("validate UI success")
|
Msg("validate UI success")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkErr(t *testing.T, err error, msg ...string) {
|
||||||
|
if err != nil {
|
||||||
|
if len(msg) == 0 {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
t.Fatal(msg, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,13 +37,3 @@ func TestDriverExt_TouchAndHold(t *testing.T) {
|
|||||||
err = driverExt.TouchAndHoldOffset(pathSearch, 0.8, 0.1)
|
err = driverExt.TouchAndHoldOffset(pathSearch, 0.8, 0.1)
|
||||||
checkErr(t, err)
|
checkErr(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkErr(t *testing.T, err error, msg ...string) {
|
|
||||||
if err != nil {
|
|
||||||
if len(msg) == 0 {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else {
|
|
||||||
t.Fatal(msg, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v4.3.0-beta-09291106
|
v4.3.0-beta-09291549
|
||||||
@@ -243,11 +243,15 @@ func (s *StepIOS) SwipeToTapText(text string, options ...uixt.ActionOption) *Ste
|
|||||||
return &StepIOS{step: s.step}
|
return &StepIOS{step: s.step}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepIOS) Input(text string) *StepIOS {
|
func (s *StepIOS) Input(text string, options ...uixt.ActionOption) *StepIOS {
|
||||||
s.step.IOS.Actions = append(s.step.IOS.Actions, uixt.MobileAction{
|
action := uixt.MobileAction{
|
||||||
Method: uixt.ACTION_Input,
|
Method: uixt.ACTION_Input,
|
||||||
Params: text,
|
Params: text,
|
||||||
})
|
}
|
||||||
|
for _, option := range options {
|
||||||
|
option(&action)
|
||||||
|
}
|
||||||
|
s.step.IOS.Actions = append(s.step.IOS.Actions, action)
|
||||||
return &StepIOS{step: s.step}
|
return &StepIOS{step: s.step}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = "v4.3.0-beta-09291106"
|
__version__ = "v4.3.0-beta-09291549"
|
||||||
__description__ = "One-stop solution for HTTP(S) testing."
|
__description__ = "One-stop solution for HTTP(S) testing."
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "httprunner"
|
name = "httprunner"
|
||||||
version = "v4.3.0-beta-09291106"
|
version = "v4.3.0-beta-09291549"
|
||||||
description = "One-stop solution for HTTP(S) testing."
|
description = "One-stop solution for HTTP(S) testing."
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
Reference in New Issue
Block a user