Merge pull request #1677 from httprunner/add-expert-test

- introduce expert test for both integration and regression
- add TapByUITypes method in step_mobile_ui.go
This commit is contained in:
debugtalk
2023-08-25 16:59:37 +08:00
committed by GitHub
7 changed files with 1286 additions and 19 deletions

View File

@@ -0,0 +1,476 @@
{
"config": {
"name": "安卓专家用例",
"variables": {
"app_name": "抖音",
"bundle_id": "com.ss.android.ugc.aweme",
"device": "${ENV(SerialNumber)}",
"query": "${ENV(query)}"
},
"android": [
{
"serial": "$device",
"uia2": true,
"log_on": true
}
]
},
"teststeps": [
{
"name": "app_launch 以及 ui_foreground_app equal 断言",
"android": {
"actions": [
{
"method": "app_launch",
"params": "$bundle_id"
},
{
"method": "sleep",
"params": 2
}
]
},
"validate": [
{
"check": "ui_foreground_app",
"assert": "equal",
"expect": "$bundle_id",
"msg": "app [$bundle_id] should be in foreground"
}
]
},
{
"name": "home 以及 swipe_to_tap_app 默认配置",
"android": {
"actions": [
{
"method": "home"
},
{
"method": "swipe_to_tap_app",
"params": "$app_name",
"options": {}
},
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言",
"android": {
"actions": [
{
"method": "tap_ocr",
"params": "我知道了",
"options": {
"ignore_NotFoundError": true
}
}
]
},
"validate": [
{
"check": "ui_ocr",
"assert": "exists",
"expect": "推荐",
"msg": "进入抖音失败"
}
]
},
{
"name": "【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置",
"android": {
"actions": [
{
"method": "swipe_to_tap_texts",
"params": [
"直播",
"直播中",
"点击进入直播间"
],
"options": {
"identifier": "click_live",
"max_retry_times": 50,
"interval": 1.5,
"direction": [
0.5,
0.7,
0.5,
0.3
],
"scope": [
0.2,
0.2,
1,
0.8
]
}
}
]
}
},
{
"name": "sleep 10s",
"android": {
"actions": [
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "【直播】swipe 自定义配置 以及 back",
"android": {
"actions": [
{
"method": "swipe",
"params": [
0.5,
0.7,
0.5,
0.3
],
"options": {
"identifier": "slide_in_live"
}
},
{
"method": "sleep",
"params": 5
},
{
"method": "back",
"options": {}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【搜索】点击放大镜 tap_xy 自定义配置",
"android": {
"actions": [
{
"method": "tap_xy",
"params": [
0.9,
0.08
],
"options": {
"identifier": "click_search_in_middle_page"
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【搜索】输入query词 input",
"android": {
"actions": [
{
"method": "input",
"params": "$query",
"options": {
"identifier": "input_query"
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【搜索】点击搜索按钮 tap_ocr 自定义配置",
"android": {
"actions": [
{
"method": "tap_ocr",
"params": "搜索",
"options": {
"identifier": "click_search_after_input_query"
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "选择直播页签 tap_ocr 默认配置",
"android": {
"actions": [
{
"method": "tap_ocr",
"params": "直播",
"options": {}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【生活服务】进入直播间 tap_xy",
"android": {
"actions": [
{
"method": "tap_xy",
"params": [
0.5,
0.5
],
"options": {}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【生活服务】点击货架商品 tap_ocr 自定义配置",
"android": {
"actions": [
{
"method": "tap_cv",
"options": {
"identifier": "click_sales_rack",
"screenshot_with_ui_types": [
"dyhouse",
"shoppingbag"
]
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "app_terminate 以及 ui_foreground_app not_equal 断言",
"android": {
"actions": [
{
"method": "app_terminate",
"params": "$bundle_id"
},
{
"method": "sleep",
"params": 2
}
]
},
"validate": [
{
"check": "ui_foreground_app",
"assert": "not_equal",
"expect": "$bundle_id",
"msg": "app [$bundle_id] should not be in foreground"
}
]
},
{
"name": "home 以及 swipe_to_tap_app 自定义配置",
"android": {
"actions": [
{
"method": "home"
},
{
"method": "swipe_to_tap_app",
"params": "$app_name",
"options": {
"max_retry_times": 5,
"interval": 1,
"offset": [
0,
-50
]
}
},
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言",
"android": {
"actions": [
{
"method": "tap_ocr",
"params": "我知道了",
"options": {
"ignore_NotFoundError": true
}
}
]
},
"validate": [
{
"check": "ui_ocr",
"assert": "exists",
"expect": "推荐",
"msg": "进入抖音失败"
}
]
},
{
"name": "【点播】滑动消费",
"android": {
"actions": [
{
"method": "video_crawler",
"params": {
"feed": {
"sleep_random": [
0,
5,
0.6,
5,
15,
0.2,
15,
50,
0.2
],
"target_count": 10,
"target_labels": [
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^广告$"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^图文$"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^特效\\|"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^模板\\|"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^购物\\|"
}
]
},
"live": {
"sleep_random": [
20,
20
],
"target_count": 0
},
"timeout": 600
}
}
]
}
},
{
"name": "返回主界面,并打开本地时间戳",
"android": {
"actions": [
{
"method": "home"
},
{
"method": "app_terminate",
"params": "$bundle_id"
},
{
"method": "sleep",
"params": 3
},
{
"method": "swipe_to_tap_app",
"params": "local",
"options": {
"max_retry_times": 5
}
},
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "screeshot 以及 sleep_random",
"android": {
"actions": [
{
"method": "screenshot",
"options": {}
},
{
"method": "sleep_random",
"params": [
1,
3
]
}
]
},
"loops": 3
}
]
}

View File

@@ -0,0 +1,325 @@
//go:build localtest
package uitest
import (
"testing"
"github.com/httprunner/httprunner/v4/hrp"
"github.com/httprunner/httprunner/v4/hrp/pkg/uixt"
)
func TestAndroidExpertTest(t *testing.T) {
testCase := &hrp.TestCase{
Config: hrp.NewConfig("安卓专家用例").
WithVariables(map[string]interface{}{
"device": "${ENV(SerialNumber)}",
"query": "${ENV(query)}",
"bundle_id": "com.ss.android.ugc.aweme",
"app_name": "抖音",
}).
SetAndroid(
uixt.WithSerialNumber("$device"),
uixt.WithAdbLogOn(true),
uixt.WithUIA2(true),
),
TestSteps: []hrp.IStep{
// 温启动
hrp.NewStep("app_launch 以及 ui_foreground_app equal 断言").
Android().
AppLaunch("$bundle_id").
Sleep(2).
Validate().
AssertAppInForeground("$bundle_id"),
hrp.NewStep("home 以及 swipe_to_tap_app 默认配置").
Android().
Home().
SwipeToTapApp("$app_name").
Sleep(10),
hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言").
Android().
TapByOCR(
"我知道了",
uixt.WithIgnoreNotFoundError(true),
).
Validate().
AssertOCRExists("推荐", "进入抖音失败"),
// 直播赛道
hrp.NewStep("【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置").
Android().
SwipeToTapTexts(
[]string{"直播", "直播中", "点击进入直播间"},
uixt.WithCustomDirection(0.5, 0.7, 0.5, 0.3),
uixt.WithScope(0.2, 0.2, 1, 0.8),
uixt.WithMaxRetryTimes(50),
uixt.WithWaitTime(1.5),
uixt.WithIdentifier("click_live"),
),
hrp.NewStep("sleep 10s").
Android().
Sleep(10),
hrp.NewStep("【直播】swipe 自定义配置 以及 back").
Android().
Swipe(
0.5, 0.7, 0.5, 0.3,
uixt.WithIdentifier("slide_in_live"),
).
Sleep(5).
Back().
Sleep(5),
// 搜索赛道
hrp.NewStep("【搜索】点击放大镜 tap_xy 自定义配置").
Android().
TapXY(
0.9, 0.08,
uixt.WithIdentifier("click_search_in_middle_page"),
).
Sleep(5),
hrp.NewStep("【搜索】输入query词 input").
Android().
Input(
"$query",
uixt.WithIdentifier("input_query"),
).
Sleep(5),
hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置").
Android().
TapByOCR(
"搜索",
uixt.WithIdentifier("click_search_after_input_query"),
uixt.WithIndex(0),
).
Sleep(5),
hrp.NewStep("选择直播页签 tap_ocr 默认配置").
Android().
TapByOCR("直播").
Sleep(5),
// 生活服务赛道
hrp.NewStep("【生活服务】进入直播间 tap_xy").
Android().
TapXY(0.5, 0.5).
Sleep(5),
hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置").
Android().
TapByUITypes(
uixt.WithScreenShotUITypes("dyhouse", "shoppingbag"),
uixt.WithIdentifier("click_sales_rack"),
).
Sleep(5),
// 冷启动
hrp.NewStep("app_terminate 以及 ui_foreground_app not_equal 断言").
Android().
AppTerminate("$bundle_id").
Sleep(2).
Validate().
AssertAppNotInForeground("$bundle_id"),
hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置").
Android().
Home().
SwipeToTapApp("$app_name", uixt.WithMaxRetryTimes(5), uixt.WithInterval(1), uixt.WithOffset(0, -50)).
Sleep(10),
hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言").
Android().
TapByOCR(
"我知道了",
uixt.WithIgnoreNotFoundError(true),
).
Validate().
AssertOCRExists("推荐", "进入抖音失败"),
// 点播赛道
hrp.NewStep("【点播】滑动消费").
Android().
VideoCrawler(map[string]interface{}{
"timeout": 600,
"feed": map[string]interface{}{
"target_count": 10,
"target_labels": []map[string]interface{}{
{"text": "^广告$", "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": "^图文$", "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": `^特效\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": `^模板\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": `^购物\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true},
},
"sleep_random": []float64{0, 5, 0.6, 5, 15, 0.2, 15, 50, 0.2},
},
"live": map[string]interface{}{
"target_count": 0,
"sleep_random": []float64{20, 20},
},
}),
// localtime 时间戳界面
hrp.NewStep("返回主界面,并打开本地时间戳").
Android().
Home().
AppTerminate("$bundle_id").
Sleep(3).
SwipeToTapApp("local", uixt.WithMaxRetryTimes(5)).Sleep(10),
hrp.NewStep("screeshot 以及 sleep_random").
Loop(3).
Android().
ScreenShot().
SleepRandom(1, 3),
},
}
if err := testCase.Dump2JSON("android_expert_test.json"); err != nil {
t.Fatal(err)
}
}
func TestIOSExpertTest(t *testing.T) {
testCase := &hrp.TestCase{
Config: hrp.NewConfig("iOS 专家用例").
WithVariables(map[string]interface{}{
"device": "${ENV(UDID)}",
"query": "${ENV(query)}",
"bundle_id": "com.ss.iphone.ugc.Aweme",
"app_name": "抖音",
}).
SetIOS(
uixt.WithUDID("$device"),
uixt.WithWDALogOn(true),
uixt.WithWDAPort(8700),
uixt.WithWDAMjpegPort(8800),
),
TestSteps: []hrp.IStep{
// 温启动
// iOS 不支持前台 App 断言操作
hrp.NewStep("启动应用程序 app_launch").
IOS().
AppLaunch("$bundle_id").
Sleep(2),
hrp.NewStep("home 以及 swipe_to_tap_app 默认配置").
IOS().
Home().
SwipeToTapApp("$app_name").
Sleep(10),
hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言").
IOS().
TapByOCR(
"我知道了",
uixt.WithIgnoreNotFoundError(true),
).
Validate().
AssertOCRExists("推荐", "进入抖音失败"),
// 直播赛道
hrp.NewStep("【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置").
IOS().
SwipeToTapTexts(
[]string{"直播", "直播中", "点击进入直播间"},
uixt.WithCustomDirection(0.5, 0.7, 0.5, 0.3),
uixt.WithScope(0.2, 0.2, 1, 0.8),
uixt.WithMaxRetryTimes(50),
uixt.WithWaitTime(1.5),
uixt.WithIdentifier("click_live"),
),
hrp.NewStep("sleep 10s").
IOS().
Sleep(10),
hrp.NewStep("【直播】swipe 自定义配置 以及 back").
IOS().
Swipe(
0.5, 0.7, 0.5, 0.3,
uixt.WithIdentifier("slide_in_live"),
).
Sleep(5).
Back().
Sleep(5),
// 搜索赛道
hrp.NewStep("【搜索】点击放大镜 tap_xy 自定义配置").
IOS().
TapXY(
0.9, 0.075,
uixt.WithIdentifier("click_search_in_middle_page"),
).
Sleep(5),
hrp.NewStep("【搜索】输入query词 input").
IOS().
Input(
"$query",
uixt.WithIdentifier("input_query"),
).
Sleep(5),
hrp.NewStep("【搜索】点击搜索按钮 tap_ocr 自定义配置").
IOS().
TapByOCR(
"搜索",
uixt.WithIdentifier("click_search_after_input_query"),
uixt.WithIndex(0),
).
Sleep(5),
// 生活服务赛道
hrp.NewStep("选择直播页签 tap_ocr 默认配置").
IOS().
TapByOCR("直播").
Sleep(5),
hrp.NewStep("【生活服务】进入直播间 tap_xy").
IOS().
TapXY(0.5, 0.5).
Sleep(5),
hrp.NewStep("【生活服务】点击货架商品 tap_ocr 自定义配置").
IOS().
TapByUITypes(
uixt.WithScreenShotUITypes("dyhouse", "shoppingbag"),
uixt.WithIdentifier("click_sales_rack"),
).
Sleep(5),
// 冷启动
// iOS 不支持前台 App 断言操作
hrp.NewStep("终止应用程序 app_terminate").
IOS().
AppTerminate("$bundle_id").
Sleep(2),
hrp.NewStep("home 以及 swipe_to_tap_app 自定义配置").
IOS().
Home().
SwipeToTapApp("$app_name", uixt.WithMaxRetryTimes(5), uixt.WithInterval(1), uixt.WithOffset(0, -50)).
Sleep(10),
hrp.NewStep("处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言").
IOS().
TapByOCR(
"我知道了",
uixt.WithIgnoreNotFoundError(true),
).
Validate().
AssertOCRExists("推荐", "进入抖音失败"),
// 点播赛道
hrp.NewStep("【点播】滑动消费").
IOS().
VideoCrawler(map[string]interface{}{
"timeout": 600,
"feed": map[string]interface{}{
"target_count": 10,
"target_labels": []map[string]interface{}{
{"text": "^广告$", "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": "^图文$", "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": `^特效\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": `^模板\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true},
{"text": `^购物\|`, "scope": []float64{0, 0.5, 1, 1}, "regex": true},
},
"sleep_random": []float64{0, 5, 0.6, 5, 15, 0.2, 15, 50, 0.2},
},
"live": map[string]interface{}{
"target_count": 0,
"sleep_random": []float64{20, 20},
},
}),
// localtime 时间戳界面
hrp.NewStep("返回主界面,并打开本地时间戳").
IOS().
Home().
AppTerminate("$bundle_id").
Sleep(3).
SwipeToTapApp("local", uixt.WithMaxRetryTimes(5)).Sleep(10),
hrp.NewStep("screeshot 以及 sleep_random").
Loop(3).
IOS().
ScreenShot().
SleepRandom(1, 3),
},
}
if err := testCase.Dump2JSON("ios_expert_test.json"); err != nil {
t.Fatal(err)
}
}

View File

@@ -0,0 +1,461 @@
{
"config": {
"name": "iOS 专家用例",
"variables": {
"app_name": "抖音",
"bundle_id": "com.ss.iphone.ugc.Aweme",
"device": "${ENV(UDID)}",
"query": "${ENV(query)}"
},
"ios": [
{
"udid": "$device",
"port": 8700,
"mjpeg_port": 8800,
"log_on": true
}
]
},
"teststeps": [
{
"name": "启动应用程序 app_launch",
"ios": {
"actions": [
{
"method": "app_launch",
"params": "$bundle_id"
},
{
"method": "sleep",
"params": 2
}
]
}
},
{
"name": "home 以及 swipe_to_tap_app 默认配置",
"ios": {
"actions": [
{
"method": "home"
},
{
"method": "swipe_to_tap_app",
"params": "$app_name",
"options": {}
},
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言",
"ios": {
"actions": [
{
"method": "tap_ocr",
"params": "我知道了",
"options": {
"ignore_NotFoundError": true
}
}
]
},
"validate": [
{
"check": "ui_ocr",
"assert": "exists",
"expect": "推荐",
"msg": "进入抖音失败"
}
]
},
{
"name": "【直播】feed头像或卡片进房 swipe_to_tap_texts 自定义配置",
"ios": {
"actions": [
{
"method": "swipe_to_tap_texts",
"params": [
"直播",
"直播中",
"点击进入直播间"
],
"options": {
"identifier": "click_live",
"max_retry_times": 50,
"interval": 1.5,
"direction": [
0.5,
0.7,
0.5,
0.3
],
"scope": [
0.2,
0.2,
1,
0.8
]
}
}
]
}
},
{
"name": "sleep 10s",
"ios": {
"actions": [
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "【直播】swipe 自定义配置 以及 back",
"ios": {
"actions": [
{
"method": "swipe",
"params": [
0.5,
0.7,
0.5,
0.3
],
"options": {
"identifier": "slide_in_live"
}
},
{
"method": "sleep",
"params": 5
},
{
"method": "back",
"options": {}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【搜索】点击放大镜 tap_xy 自定义配置",
"ios": {
"actions": [
{
"method": "tap_xy",
"params": [
0.9,
0.075
],
"options": {
"identifier": "click_search_in_middle_page"
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【搜索】输入query词 input",
"ios": {
"actions": [
{
"method": "input",
"params": "$query",
"options": {
"identifier": "input_query"
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【搜索】点击搜索按钮 tap_ocr 自定义配置",
"ios": {
"actions": [
{
"method": "tap_ocr",
"params": "搜索",
"options": {
"identifier": "click_search_after_input_query"
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "选择直播页签 tap_ocr 默认配置",
"ios": {
"actions": [
{
"method": "tap_ocr",
"params": "直播",
"options": {}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【生活服务】进入直播间 tap_xy",
"ios": {
"actions": [
{
"method": "tap_xy",
"params": [
0.5,
0.5
],
"options": {}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "【生活服务】点击货架商品 tap_ocr 自定义配置",
"ios": {
"actions": [
{
"method": "tap_cv",
"options": {
"identifier": "click_sales_rack",
"screenshot_with_ui_types": [
"dyhouse",
"shoppingbag"
]
}
},
{
"method": "sleep",
"params": 5
}
]
}
},
{
"name": "终止应用程序 app_terminate",
"ios": {
"actions": [
{
"method": "app_terminate",
"params": "$bundle_id"
},
{
"method": "sleep",
"params": 2
}
]
}
},
{
"name": "home 以及 swipe_to_tap_app 自定义配置",
"ios": {
"actions": [
{
"method": "home"
},
{
"method": "swipe_to_tap_app",
"params": "$app_name",
"options": {
"max_retry_times": 5,
"interval": 1,
"offset": [
0,
-50
]
}
},
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "处理青少年弹窗 tap ocr 以及 ui_ocr exists 断言",
"ios": {
"actions": [
{
"method": "tap_ocr",
"params": "我知道了",
"options": {
"ignore_NotFoundError": true
}
}
]
},
"validate": [
{
"check": "ui_ocr",
"assert": "exists",
"expect": "推荐",
"msg": "进入抖音失败"
}
]
},
{
"name": "【点播】滑动消费",
"ios": {
"actions": [
{
"method": "video_crawler",
"params": {
"feed": {
"sleep_random": [
0,
5,
0.6,
5,
15,
0.2,
15,
50,
0.2
],
"target_count": 10,
"target_labels": [
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^广告$"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^图文$"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^特效\\|"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^模板\\|"
},
{
"regex": true,
"scope": [
0,
0.5,
1,
1
],
"text": "^购物\\|"
}
]
},
"live": {
"sleep_random": [
20,
20
],
"target_count": 0
},
"timeout": 600
}
}
]
}
},
{
"name": "返回主界面,并打开本地时间戳",
"ios": {
"actions": [
{
"method": "home"
},
{
"method": "app_terminate",
"params": "$bundle_id"
},
{
"method": "sleep",
"params": 3
},
{
"method": "swipe_to_tap_app",
"params": "local",
"options": {
"max_retry_times": 5
}
},
{
"method": "sleep",
"params": 10
}
]
}
},
{
"name": "screeshot 以及 sleep_random",
"ios": {
"actions": [
{
"method": "screenshot",
"options": {}
},
{
"method": "sleep_random",
"params": [
1,
3
]
}
]
},
"loops": 3
}
]
}

View File

@@ -547,17 +547,8 @@ func (dExt *DriverExt) DoAction(action MobileAction) (err error) {
case ACTION_TapByCV:
if imagePath, ok := action.Params.(string); ok {
return dExt.TapByCV(imagePath, action.GetOptions()...)
}
if uiParams, ok := action.Params.([]interface{}); ok {
var uiTypes []string
for _, uiParam := range uiParams {
uiType, ok := uiParam.(string)
if !ok {
continue
}
uiTypes = append(uiTypes, uiType)
}
return dExt.TapByUIDetection(uiTypes, action.Options.Options()...)
} else if err := dExt.TapByUIDetection(action.GetOptions()...); err == nil {
return nil
}
return fmt.Errorf("invalid %s params: %v", ACTION_TapByCV, action.Params)
case ACTION_DoubleTapXY:

View File

@@ -478,6 +478,7 @@ func (u UIResults) FilterScope(scope AbsScope) (results UIResults) {
type UIResultMap map[string]UIResults
// FilterUIResults filters ui icons, the former the uiTypes, the higher the priority
func (u UIResultMap) FilterUIResults(uiTypes []string) (uiResults UIResults, err error) {
var ok bool
for _, uiType := range uiTypes {
@@ -512,20 +513,22 @@ func (u UIResults) GetUIResult(options ...ActionOption) (UIResult, error) {
return uiResults[idx], nil
}
func (dExt *DriverExt) FindUIResult(uiTypes []string, options ...ActionOption) (point PointF, err error) {
screenResult, err := dExt.GetScreenResult(WithScreenShotUITypes(uiTypes...))
func (dExt *DriverExt) FindUIResult(options ...ActionOption) (point PointF, err error) {
actionOptions := NewActionOptions(options...)
screenResult, err := dExt.GetScreenResult(options...)
if err != nil {
return
}
uiResults, err := screenResult.Icons.FilterUIResults(uiTypes)
uiResults, err := screenResult.Icons.FilterUIResults(actionOptions.ScreenShotWithUITypes)
if err != nil {
return
}
uiResult, err := uiResults.GetUIResult(dExt.ParseActionOptions(options...)...)
point = uiResult.Center()
log.Info().Interface("text", uiTypes).
log.Info().Interface("text", actionOptions.ScreenShotWithUITypes).
Interface("point", point).Msg("FindUIResult success")
return
}

View File

@@ -49,10 +49,10 @@ func (dExt *DriverExt) TapByCV(imagePath string, options ...ActionOption) error
return dExt.TapAbsXY(point.X, point.Y, options...)
}
func (dExt *DriverExt) TapByUIDetection(uiTypes []string, options ...ActionOption) error {
func (dExt *DriverExt) TapByUIDetection(options ...ActionOption) error {
actionOptions := NewActionOptions(options...)
point, err := dExt.FindUIResult(uiTypes, options...)
point, err := dExt.FindUIResult(options...)
if err != nil {
if actionOptions.IgnoreNotFoundError {
return nil

View File

@@ -102,7 +102,7 @@ func (s *StepMobile) Tap(params string, options ...uixt.ActionOption) *StepMobil
return &StepMobile{step: s.step}
}
// Tap taps on the target element by OCR recognition
// TapByOCR taps on the target element by OCR recognition
func (s *StepMobile) TapByOCR(ocrText string, options ...uixt.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapByOCR,
@@ -114,7 +114,7 @@ func (s *StepMobile) TapByOCR(ocrText string, options ...uixt.ActionOption) *Ste
return &StepMobile{step: s.step}
}
// Tap taps on the target element by CV recognition
// TapByCV taps on the target element by CV recognition
func (s *StepMobile) TapByCV(imagePath string, options ...uixt.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV,
@@ -126,6 +126,17 @@ func (s *StepMobile) TapByCV(imagePath string, options ...uixt.ActionOption) *St
return &StepMobile{step: s.step}
}
// TapByUITypes taps on the target element specified by uiTypes, the higher the uiTypes, the higher the priority
func (s *StepMobile) TapByUITypes(options ...uixt.ActionOption) *StepMobile {
action := uixt.MobileAction{
Method: uixt.ACTION_TapByCV,
Options: uixt.NewActionOptions(options...),
}
s.mobileStep().Actions = append(s.mobileStep().Actions, action)
return &StepMobile{step: s.step}
}
// DoubleTapXY double taps the point {X,Y}, X & Y is percentage of coordinates
func (s *StepMobile) DoubleTapXY(x, y float64, options ...uixt.ActionOption) *StepMobile {
s.mobileStep().Actions = append(s.mobileStep().Actions, uixt.MobileAction{