mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-11 10:00:23 +08:00
Merge branch 'examples' into 'master'
refactor browser session setup See merge request iesqa/httprunner!114
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"config": {
|
||||
"name": "浪漫餐厅小游戏自动化测试",
|
||||
"variables": {
|
||||
"package_name": "com.ss.android.ugc.aweme"
|
||||
},
|
||||
"ai_options": {
|
||||
"llm_service": "doubao-1.5-thinking-vision-pro-250428"
|
||||
}
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "启动抖音 app",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_launch",
|
||||
"params": "$package_name"
|
||||
},
|
||||
{
|
||||
"method": "sleep",
|
||||
"params": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "ui_foreground_app",
|
||||
"assert": "equal",
|
||||
"expect": "$package_name",
|
||||
"msg": "app [$package_name] should be in foreground"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "进入「浪漫餐厅」小游戏",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "start_to_goal",
|
||||
"params": "搜索「浪漫餐厅」,进入小游戏",
|
||||
"options": {
|
||||
"pre_mark_operation": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "ui_ai",
|
||||
"assert": "ai_assert",
|
||||
"expect": "当前位于游戏界面",
|
||||
"msg": "assert ai prompt [当前位于游戏界面] failed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "开始游戏",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "start_to_goal",
|
||||
"params": "浪漫餐厅是一款经营类游戏,以下是游戏的基本规则说明:\n1、点击右下角锅铲,开始任务\n2、将棋子拖拽至相同棋子,可升级生成新棋子\n3、拖拽相同棋子时,被部分遮挡的棋子只能作为拖拽终点,不能作为拖拽起点\n4、当游戏界面中没有相同棋子时,可以点击游戏页面中央的购物袋生成新的棋子\n5、若不知道如何操作,请按照游戏指引进行游玩\n\n请严格按照以上游戏规则,开始游戏\n",
|
||||
"options": {
|
||||
"timeout": 300,
|
||||
"pre_mark_operation": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "退出抖音 app",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_terminate",
|
||||
"params": "$package_name"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
56
examples/game/romantic_restaurant/main_test.go
Normal file
56
examples/game/romantic_restaurant/main_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package game_romantic_restaurant
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
hrp "github.com/httprunner/httprunner/v5"
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
)
|
||||
|
||||
func TestGameRomanticRestaurant(t *testing.T) {
|
||||
userInstruction := `浪漫餐厅是一款经营类游戏,以下是游戏的基本规则说明:
|
||||
1、点击右下角锅铲,开始任务
|
||||
2、将棋子拖拽至相同棋子,可升级生成新棋子
|
||||
3、拖拽相同棋子时,被部分遮挡的棋子只能作为拖拽终点,不能作为拖拽起点
|
||||
4、当游戏界面中没有相同棋子时,可以点击游戏页面中央的购物袋生成新的棋子
|
||||
5、若不知道如何操作,请按照游戏指引进行游玩
|
||||
|
||||
请严格按照以上游戏规则,开始游戏
|
||||
`
|
||||
testCase := &hrp.TestCase{
|
||||
Config: hrp.NewConfig("浪漫餐厅小游戏自动化测试").
|
||||
SetLLMService(option.DOUBAO_1_5_THINKING_VISION_PRO_250428).
|
||||
WithVariables(map[string]interface{}{
|
||||
"package_name": "com.ss.android.ugc.aweme",
|
||||
}),
|
||||
TestSteps: []hrp.IStep{
|
||||
hrp.NewStep("启动抖音 app").
|
||||
Android().
|
||||
AppLaunch("$package_name").
|
||||
Sleep(5).
|
||||
Validate().
|
||||
AssertAppInForeground("$package_name"),
|
||||
hrp.NewStep("进入「浪漫餐厅」小游戏").
|
||||
Android().
|
||||
StartToGoal("搜索「浪漫餐厅」,进入小游戏",
|
||||
option.WithPreMarkOperation(true)).
|
||||
Validate().
|
||||
AssertAI("当前位于游戏界面"),
|
||||
hrp.NewStep("开始游戏").
|
||||
Android().
|
||||
StartToGoal(userInstruction,
|
||||
option.WithPreMarkOperation(true),
|
||||
option.WithTimeout(300)), // 5 minutes
|
||||
hrp.NewStep("退出抖音 app").
|
||||
Android().
|
||||
AppTerminate("$package_name"),
|
||||
},
|
||||
}
|
||||
err := testCase.Dump2JSON("game_romantic_restaurant.json")
|
||||
require.Nil(t, err)
|
||||
|
||||
// err = hrp.NewRunner(t).Run(testCase)
|
||||
// assert.Nil(t, err)
|
||||
}
|
||||
88
examples/game/sudoku/game_sudoku.json
Normal file
88
examples/game/sudoku/game_sudoku.json
Normal file
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"config": {
|
||||
"name": "每天数独小游戏自动化测试",
|
||||
"variables": {
|
||||
"package_name": "com.ss.android.ugc.aweme"
|
||||
},
|
||||
"ai_options": {
|
||||
"llm_service": "doubao-1.5-thinking-vision-pro-250428"
|
||||
}
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "启动抖音 app",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_launch",
|
||||
"params": "$package_name"
|
||||
},
|
||||
{
|
||||
"method": "sleep",
|
||||
"params": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "ui_foreground_app",
|
||||
"assert": "equal",
|
||||
"expect": "$package_name",
|
||||
"msg": "app [$package_name] should be in foreground"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "进入「每天数独」小游戏",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "start_to_goal",
|
||||
"params": "搜索「每天数独」,进入小游戏",
|
||||
"options": {
|
||||
"pre_mark_operation": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "ui_ai",
|
||||
"assert": "ai_assert",
|
||||
"expect": "当前页面底部包含「开始」按钮",
|
||||
"msg": "assert ai prompt [当前页面底部包含「开始」按钮] failed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "开始游戏",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "start_to_goal",
|
||||
"params": "每天数独是一款逻辑推理游戏,玩家需要通过推理来确定黄色方块的所在位置,以下是游戏的基本规则说明:\n1、方块外面的数字代表所在那一行或一列的黄色方块数量。\n2、初始状态为白色方块,选择正确后变为黄色方块,选择错误后变为红底的 X。\n3、如果同一行或列有两个数字,则至少需要一个白底 X 分割它们作为间隔。\n4、如果数字与格子最大数相同时,该列或行必然全都是黄色方块。\n5、只能点击白色方块,不要重复点击同一个方块。\n\n请严格按照以上游戏规则,开始游戏\n",
|
||||
"options": {
|
||||
"timeout": 300,
|
||||
"pre_mark_operation": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "退出抖音 app",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_terminate",
|
||||
"params": "$package_name"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +1,56 @@
|
||||
package game_sudoku
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
hrp "github.com/httprunner/httprunner/v5"
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
)
|
||||
|
||||
func TestGameSudoku(t *testing.T) {
|
||||
userInstruction := `每天数独是一款逻辑推理游戏,玩家需要通过推理来确定黄色方块的所在位置,以下是游戏的基本规则说明:
|
||||
1、方块外面的数字代表所在那一行或一列的黄色方块数量。
|
||||
2、初始状态为白色方块,选择正确后变为黄色方块,选择错误后变为红底的 X。
|
||||
3、如果同一行或列有两个数字,则至少需要一个白底 X 分割它们作为间隔。
|
||||
4、如果数字与格子最大数相同时,该列或行必然全都是黄色方块。
|
||||
5、只能点击白色方块,不要重复点击同一个方块。
|
||||
|
||||
请严格按照以上游戏规则,开始游戏
|
||||
`
|
||||
testCase := &hrp.TestCase{
|
||||
Config: hrp.NewConfig("每天数独小游戏自动化测试").
|
||||
SetLLMService(option.DOUBAO_1_5_THINKING_VISION_PRO_250428).
|
||||
WithVariables(map[string]interface{}{
|
||||
"package_name": "com.ss.android.ugc.aweme",
|
||||
}),
|
||||
TestSteps: []hrp.IStep{
|
||||
hrp.NewStep("启动抖音 app").
|
||||
Android().
|
||||
AppLaunch("$package_name").
|
||||
Sleep(5).
|
||||
Validate().
|
||||
AssertAppInForeground("$package_name"),
|
||||
hrp.NewStep("进入「每天数独」小游戏").
|
||||
Android().
|
||||
StartToGoal("搜索「每天数独」,进入小游戏",
|
||||
option.WithPreMarkOperation(true)).
|
||||
Validate().
|
||||
AssertAI("当前页面底部包含「开始」按钮"),
|
||||
hrp.NewStep("开始游戏").
|
||||
Android().
|
||||
StartToGoal(userInstruction,
|
||||
option.WithPreMarkOperation(true),
|
||||
option.WithTimeout(300)), // 5 minutes
|
||||
hrp.NewStep("退出抖音 app").
|
||||
Android().
|
||||
AppTerminate("$package_name"),
|
||||
},
|
||||
}
|
||||
err := testCase.Dump2JSON("game_sudoku.json")
|
||||
require.Nil(t, err)
|
||||
|
||||
// err = hrp.NewRunner(t).Run(testCase)
|
||||
// assert.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"config": {
|
||||
"name": "羊了个羊小游戏自动化测试",
|
||||
"variables": {
|
||||
"package_name": "com.ss.android.ugc.aweme"
|
||||
},
|
||||
"ai_options": {
|
||||
"llm_service": "doubao-1.5-thinking-vision-pro-250428"
|
||||
}
|
||||
@@ -13,7 +16,7 @@
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_launch",
|
||||
"params": "com.ss.android.ugc.aweme"
|
||||
"params": "$package_name"
|
||||
},
|
||||
{
|
||||
"method": "sleep",
|
||||
@@ -25,8 +28,8 @@
|
||||
{
|
||||
"check": "ui_foreground_app",
|
||||
"assert": "equal",
|
||||
"expect": "com.ss.android.ugc.aweme",
|
||||
"msg": "app [com.ss.android.ugc.aweme] should be in foreground"
|
||||
"expect": "$package_name",
|
||||
"msg": "app [$package_name] should be in foreground"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -68,6 +71,18 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "退出抖音 app",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_terminate",
|
||||
"params": "$package_name"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -28,14 +28,17 @@ func TestGameYanglegeyang(t *testing.T) {
|
||||
|
||||
testCase := &hrp.TestCase{
|
||||
Config: hrp.NewConfig("羊了个羊小游戏自动化测试").
|
||||
SetLLMService(option.DOUBAO_1_5_THINKING_VISION_PRO_250428),
|
||||
SetLLMService(option.DOUBAO_1_5_THINKING_VISION_PRO_250428).
|
||||
WithVariables(map[string]interface{}{
|
||||
"package_name": "com.ss.android.ugc.aweme",
|
||||
}),
|
||||
TestSteps: []hrp.IStep{
|
||||
hrp.NewStep("启动抖音 app").
|
||||
Android().
|
||||
AppLaunch("com.ss.android.ugc.aweme").
|
||||
AppLaunch("$package_name").
|
||||
Sleep(5).
|
||||
Validate().
|
||||
AssertAppInForeground("com.ss.android.ugc.aweme"),
|
||||
AssertAppInForeground("$package_name"),
|
||||
hrp.NewStep("进入「羊了个羊」小游戏").
|
||||
Android().
|
||||
StartToGoal("搜索「羊了个羊星球」,进入小程序,加入羊群进入游戏",
|
||||
@@ -47,6 +50,9 @@ func TestGameYanglegeyang(t *testing.T) {
|
||||
StartToGoal(userInstruction,
|
||||
option.WithPreMarkOperation(true),
|
||||
option.WithTimeout(300)), // 5 minutes
|
||||
hrp.NewStep("退出抖音 app").
|
||||
Android().
|
||||
AppTerminate("$package_name"),
|
||||
},
|
||||
}
|
||||
err := testCase.Dump2JSON("game_yanglegeyang.json")
|
||||
|
||||
111
examples/game/zhuadae/game_zhuadae.json
Normal file
111
examples/game/zhuadae/game_zhuadae.json
Normal file
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"config": {
|
||||
"name": "抓大鹅小游戏自动化测试",
|
||||
"variables": {
|
||||
"package_name": "com.ss.android.ugc.aweme"
|
||||
},
|
||||
"ai_options": {
|
||||
"llm_service": "doubao-1.5-thinking-vision-pro-250428"
|
||||
}
|
||||
},
|
||||
"teststeps": [
|
||||
{
|
||||
"name": "启动抖音 app",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_launch",
|
||||
"params": "$package_name"
|
||||
},
|
||||
{
|
||||
"method": "sleep",
|
||||
"params": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "ui_foreground_app",
|
||||
"assert": "equal",
|
||||
"expect": "$package_name",
|
||||
"msg": "app [$package_name] should be in foreground"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "启动「抓大鹅」小游戏",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "start_to_goal",
|
||||
"params": "搜索「抓大鹅」,启动小游戏",
|
||||
"options": {
|
||||
"pre_mark_operation": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "ui_ai",
|
||||
"assert": "ai_assert",
|
||||
"expect": "当前页面底部包含「抓大鹅」按钮",
|
||||
"msg": "assert ai prompt [当前页面底部包含「抓大鹅」按钮] failed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "进入「抓大鹅」小游戏",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "start_to_goal",
|
||||
"params": "点击「抓大鹅」,进入小游戏",
|
||||
"options": {
|
||||
"pre_mark_operation": true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"validate": [
|
||||
{
|
||||
"check": "ui_ai",
|
||||
"assert": "ai_assert",
|
||||
"expect": "当前页面底部包含「移出」「凑齐」「打乱」按钮",
|
||||
"msg": "assert ai prompt [当前页面底部包含「移出」「凑齐」「打乱」按钮] failed"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "开始游戏",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "start_to_goal",
|
||||
"params": "抓大鹅是一款抓取类小游戏,以下是游戏的基本规则说明:\n1. 游戏目标: 玩家需要通过抓取图案来完成关卡,最终目标是清空所有图案。\n2. 抓取规则:\n- 游戏界面中会出现多个图案,图案存在多层堆叠的情况,玩家需要点击图案将其抓取放入到槽中。\n- 当抓取到三个相同的图案放入抓取槽时,这三个图案会成功消除。\n- 需要尽量避免抓取槽满的情况,抓取槽满时游戏失败。\n- 游戏通关后继续进入下一关,游戏失败后重新开始游戏。\n\n请严格按照以上游戏规则,开始游戏\n",
|
||||
"options": {
|
||||
"timeout": 300,
|
||||
"pre_mark_operation": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "退出抖音 app",
|
||||
"android": {
|
||||
"os_type": "android",
|
||||
"actions": [
|
||||
{
|
||||
"method": "app_terminate",
|
||||
"params": "$package_name"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
64
examples/game/zhuadae/main_test.go
Normal file
64
examples/game/zhuadae/main_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package game_zhuadae
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
hrp "github.com/httprunner/httprunner/v5"
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
)
|
||||
|
||||
func TestGameZhuadaE(t *testing.T) {
|
||||
userInstruction := `抓大鹅是一款抓取类小游戏,以下是游戏的基本规则说明:
|
||||
1. 游戏目标: 玩家需要通过抓取图案来完成关卡,最终目标是清空所有图案。
|
||||
2. 抓取规则:
|
||||
- 游戏界面中会出现多个图案,图案存在多层堆叠的情况,玩家需要点击图案将其抓取放入到槽中。
|
||||
- 当抓取到三个相同的图案放入抓取槽时,这三个图案会成功消除。
|
||||
- 需要尽量避免抓取槽满的情况,抓取槽满时游戏失败。
|
||||
- 游戏通关后继续进入下一关,游戏失败后重新开始游戏。
|
||||
|
||||
请严格按照以上游戏规则,开始游戏
|
||||
`
|
||||
|
||||
testCase := &hrp.TestCase{
|
||||
Config: hrp.NewConfig("抓大鹅小游戏自动化测试").
|
||||
SetLLMService(option.DOUBAO_1_5_THINKING_VISION_PRO_250428).
|
||||
WithVariables(map[string]interface{}{
|
||||
"package_name": "com.ss.android.ugc.aweme",
|
||||
}),
|
||||
TestSteps: []hrp.IStep{
|
||||
hrp.NewStep("启动抖音 app").
|
||||
Android().
|
||||
AppLaunch("$package_name").
|
||||
Sleep(5).
|
||||
Validate().
|
||||
AssertAppInForeground("$package_name"),
|
||||
hrp.NewStep("启动「抓大鹅」小游戏").
|
||||
Android().
|
||||
StartToGoal("搜索「抓大鹅」,启动小游戏",
|
||||
option.WithPreMarkOperation(true)).
|
||||
Validate().
|
||||
AssertAI("当前页面底部包含「抓大鹅」按钮"),
|
||||
hrp.NewStep("进入「抓大鹅」小游戏").
|
||||
Android().
|
||||
StartToGoal("点击「抓大鹅」,进入小游戏",
|
||||
option.WithPreMarkOperation(true)).
|
||||
Validate().
|
||||
AssertAI("当前页面底部包含「移出」「凑齐」「打乱」按钮"),
|
||||
hrp.NewStep("开始游戏").
|
||||
Android().
|
||||
StartToGoal(userInstruction,
|
||||
option.WithPreMarkOperation(true),
|
||||
option.WithTimeout(300)), // 5 minutes
|
||||
hrp.NewStep("退出抖音 app").
|
||||
Android().
|
||||
AppTerminate("$package_name"),
|
||||
},
|
||||
}
|
||||
err := testCase.Dump2JSON("game_zhuadae.json")
|
||||
require.Nil(t, err)
|
||||
|
||||
// err = hrp.NewRunner(t).Run(testCase)
|
||||
// assert.Nil(t, err)
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
v5.0.0-250630
|
||||
v5.0.0-250701
|
||||
|
||||
@@ -36,9 +36,7 @@ import (
|
||||
|
||||
// Run starts to run testcase with default configs.
|
||||
func Run(t *testing.T, testcases ...ITestCase) error {
|
||||
err := NewRunner(t).SetSaveTests(true).Run(testcases...)
|
||||
code.GetErrorCode(err)
|
||||
return err
|
||||
return NewRunner(t).SetSaveTests(true).Run(testcases...)
|
||||
}
|
||||
|
||||
// NewRunner constructs a new runner instance.
|
||||
@@ -234,7 +232,9 @@ func (r *HRPRunner) Run(testcases ...ITestCase) (err error) {
|
||||
// this ensures they run regardless of how the function exits
|
||||
defer func() {
|
||||
s.Time.Duration = time.Since(s.Time.StartAt).Seconds()
|
||||
log.Info().Int("duration(s)", int(s.Time.Duration)).Msg("run testcase finished")
|
||||
exitCode := code.GetErrorCode(err)
|
||||
log.Info().Int("duration(s)", int(s.Time.Duration)).
|
||||
Int("exitCode", exitCode).Msg("run testcase finished")
|
||||
|
||||
// save summary
|
||||
if r.saveTests {
|
||||
|
||||
@@ -14,13 +14,14 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/httprunner/httprunner/v5/code"
|
||||
"github.com/httprunner/httprunner/v5/internal/json"
|
||||
"github.com/httprunner/httprunner/v5/internal/version"
|
||||
"github.com/httprunner/httprunner/v5/uixt"
|
||||
"github.com/httprunner/httprunner/v5/uixt/option"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type UIXTRunner struct {
|
||||
@@ -219,7 +220,7 @@ func (configs *UIXTConfig) getWDALocalPort(udid string) (string, error) {
|
||||
"device_id": udid,
|
||||
})
|
||||
req, err := http.NewRequest("POST",
|
||||
fmt.Sprintf("http://127.0.0.1:%d/get_device_port", configs.WDAMjpegPort),
|
||||
fmt.Sprintf("http://localhost:%d/get_device_port", configs.WDAMjpegPort),
|
||||
bytes.NewBuffer(payloadBytes))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "create request failed")
|
||||
|
||||
@@ -19,7 +19,7 @@ import (
|
||||
"github.com/httprunner/httprunner/v5/uixt/types"
|
||||
)
|
||||
|
||||
const BROWSER_LOCAL_ADDRESS = "localhost:8093"
|
||||
const BROWSER_BASE_URL = "http://localhost:8093"
|
||||
|
||||
type WebAgentResponse struct {
|
||||
Code int `json:"code"`
|
||||
@@ -35,9 +35,8 @@ type CreateBrowserResponse struct {
|
||||
}
|
||||
|
||||
type BrowserDriver struct {
|
||||
urlPrefix *url.URL
|
||||
Session *DriverSession
|
||||
Device *BrowserDevice
|
||||
Session *DriverSession
|
||||
Device *BrowserDevice
|
||||
}
|
||||
|
||||
type BrowserInfo struct {
|
||||
@@ -61,7 +60,7 @@ func CreateBrowser(timeout int, width, height int) (browserInfo *BrowserInfo, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawURL := "http://" + BROWSER_LOCAL_ADDRESS + "/api/v1/create_browser"
|
||||
rawURL := BROWSER_BASE_URL + "/api/v1/create_browser"
|
||||
req, err := http.NewRequest(http.MethodPost, rawURL, bytes.NewBuffer(bsJSON))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
@@ -98,20 +97,23 @@ func NewBrowserDriver(device *BrowserDevice) (driver *BrowserDriver, err error)
|
||||
log.Info().Msg("init NewBrowserDriver driver")
|
||||
driver = new(BrowserDriver)
|
||||
driver.Device = device
|
||||
driver.urlPrefix = &url.URL{}
|
||||
driver.urlPrefix.Host = BROWSER_LOCAL_ADDRESS
|
||||
driver.urlPrefix.Scheme = "http"
|
||||
driver.Session = NewDriverSession()
|
||||
driver.Session.ID = device.UUID()
|
||||
|
||||
err = driver.Setup()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "setup browser driver failed")
|
||||
}
|
||||
|
||||
return driver, nil
|
||||
}
|
||||
|
||||
func (wd *BrowserDriver) Setup() error {
|
||||
wd.Session = NewDriverSession()
|
||||
err := wd.Session.SetupPortForward(8093)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wd.Session.SetBaseURL(BROWSER_LOCAL_ADDRESS)
|
||||
wd.Session.SetBaseURL(BROWSER_BASE_URL)
|
||||
wd.Session.ID = wd.Device.UUID()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -263,7 +265,7 @@ func (wd *BrowserDriver) SecondaryClickBySelector(selector string, options ...op
|
||||
|
||||
func (wd *BrowserDriver) GetElementTextBySelector(selector string, options ...option.ActionOption) (text string, err error) {
|
||||
actionOptions := option.NewActionOptions(options...)
|
||||
baseURL := fmt.Sprintf("http://%s/api/v1/%s/element_text", BROWSER_LOCAL_ADDRESS, wd.Session.ID)
|
||||
baseURL := fmt.Sprintf("%s/api/v1/%s/element_text", BROWSER_BASE_URL, wd.Session.ID)
|
||||
|
||||
// 使用 url.Values 构建查询参数
|
||||
params := url.Values{}
|
||||
@@ -404,10 +406,7 @@ func (wd *BrowserDriver) ScreenShot(options ...option.ActionOption) (*bytes.Buff
|
||||
}
|
||||
|
||||
func (wd *BrowserDriver) concatURL(elem ...string) string {
|
||||
tmp, _ := url.Parse(wd.urlPrefix.String())
|
||||
commonPath := path.Join(append([]string{wd.urlPrefix.Path}, "api/v1/")...)
|
||||
tmp.Path = path.Join(append([]string{commonPath}, elem...)...)
|
||||
return tmp.String()
|
||||
return path.Join(append([]string{"/api/v1"}, elem...)...)
|
||||
}
|
||||
|
||||
func (wd *BrowserDriver) Status() (deviceStatus types.DeviceStatus, err error) {
|
||||
|
||||
Reference in New Issue
Block a user