diff --git a/examples/uitest/android_follow_live_test.json b/examples/uitest/android_follow_live_test.json index e1c57a25..3c50234c 100644 --- a/examples/uitest/android_follow_live_test.json +++ b/examples/uitest/android_follow_live_test.json @@ -25,22 +25,6 @@ { "method": "app_launch", "params": "com.ss.android.ugc.aweme" - }, - { - "method": "home" - }, - { - "method": "swipe_to_tap_app", - "params": "抖音", - "max_retry_times": 5, - "offset": [ - 0, - -50 - ] - }, - { - "method": "sleep", - "params": 20 } ] } @@ -72,121 +56,11 @@ { "method": "tap_ocr", "params": "关注", - "index": -1 - }, - { - "method": "sleep", - "params": 10 + "index": -1, + "identifier": "click_live_new" } ] } - }, - { - "name": "点击直播标签,进入直播间", - "android": { - "actions": [ - { - "method": "swipe_to_tap_texts", - "params": "${split_by_comma($ups)}", - "identifier": "click_live", - "wait_time": 1, - "direction": [ - 0.6, - 0.2, - 0.4, - 0.2 - ], - "offset": [ - 0, - -50 - ] - } - ] - } - }, - { - "name": "等待1分钟", - "android": { - "actions": [ - { - "method": "sleep", - "params": 30 - } - ] - } - }, - { - "name": "上滑进入下一个直播间", - "android": { - "actions": [ - { - "method": "swipe", - "params": [ - 0.9, - 0.9, - 0.9, - 0.1 - ], - "identifier": "slide_in_live" - }, - { - "method": "sleep", - "params": 30 - } - ] - } - }, - { - "name": "再上滑进入下一个直播间", - "android": { - "actions": [ - { - "method": "swipe", - "params": [ - 0.9, - 0.9, - 0.9, - 0.1 - ], - "identifier": "slide_in_live" - }, - { - "method": "sleep", - "params": 30 - } - ] - } - }, - { - "name": "返回主界面,并打开本地时间戳", - "android": { - "actions": [ - { - "method": "home" - }, - { - "method": "swipe_to_tap_app", - "params": "local", - "max_retry_times": 5, - "offset": [ - 0, - -50 - ] - }, - { - "method": "sleep", - "params": 10 - } - ] - }, - "validate": [ - { - "check": "ui_ocr", - "assert": "exists", - "expect": "16", - "msg": "打开本地时间戳失败" - } - ] } ] } \ No newline at end of file diff --git a/examples/uitest/demo_android_feed_swipe.json b/examples/uitest/demo_android_feed_swipe.json index c50ba576..7f8fe3bc 100644 --- a/examples/uitest/demo_android_feed_swipe.json +++ b/examples/uitest/demo_android_feed_swipe.json @@ -1,27 +1,223 @@ { "config": { - "name": "点播_抖音_滑动场景_随机间隔_android", + "name": "直播_抖极_feed卡片_android", "variables": { "device": "${ENV(SerialNumber)}" }, "android": [ { - "serial": "$device" + "serial": "$device", + "log_on": true, + "close_popup": true } ] }, "teststeps": [ { - "name": "启动抖音", + "name": "清理android无关进程", "android": { "actions": [ { "method": "app_terminate", "params": "com.ss.android.ugc.aweme" }, + { + "method": "app_terminate", + "params": "com.ss.android.ugc.aweme.lite" + }, + { + "method": "app_terminate", + "params": "com.smile.gifmaker" + }, + { + "method": "app_terminate", + "params": "com.kuaishou.nebula" + }, + { + "method": "app_terminate", + "params": "com.tencent.mm" + }, + { + "method": "app_terminate", + "params": "com.duowan.kiwi" + }, + { + "method": "app_terminate", + "params": "air.tv.douyu.android" + }, + { + "method": "app_terminate", + "params": "com.xingin.xhs" + }, + { + "method": "app_terminate", + "params": "com.taobao.taobao" + }, + { + "method": "app_terminate", + "params": "tv.danmaku.bili" + }, + { + "method": "app_terminate", + "params": "com.cmcc.cmvideo" + }, + { + "method": "app_terminate", + "params": "com.xunmeng.pinduoduo" + }, + { + "method": "app_terminate", + "params": "com.cctv.yangshipin.app.androidp" + } + ] + } + }, + { + "name": "启动抖音极速版", + "android": { + "actions": [ + { + "method": "app_terminate", + "params": "com.ss.android.ugc.aweme.lite" + }, { "method": "app_launch", - "params": "com.ss.android.ugc.aweme" + "params": "com.ss.android.ugc.aweme.lite" + }, + { + "method": "sleep", + "params": 10 + }, + { + "method": "close_popups", + "options": { + "max_retry_times": 2 + } + } + ] + }, + "validate": [ + { + "check": "ui_foreground_app", + "assert": "equal", + "expect": "com.ss.android.ugc.aweme.lite", + "msg": "app [com.ss.android.ugc.aweme.lite] should be in foreground" + } + ] + }, + { + "name": "处理通讯录弹窗", + "android": { + "actions": [ + { + "method": "tap_ocr", + "params": "拒绝", + "ignore_NotFoundError": true + } + ] + } + }, + { + "name": "处理青少年弹窗", + "android": { + "actions": [ + { + "method": "sleep", + "params": 5 + }, + { + "method": "tap_ocr", + "params": "我知道了", + "ignore_NotFoundError": true + } + ] + } + }, + { + "name": "点击直播标签,进入直播间", + "android": { + "actions": [ + { + "method": "swipe_to_tap_texts", + "params": [ + "看直播开宝箱", + "最高领", + "点击进入直播间" + ], + "identifier": "click_live_new", + "max_retry_times": 40, + "wait_time": 2, + "direction": [ + 0.5, + 0.8, + 0.5, + 0.2 + ], + "scope": [ + 0.1, + 0.5, + 0.9, + 0.9 + ], + "offset": [ + 0, + -100 + ] + } + ] + } + }, + { + "name": "等待30s", + "android": { + "actions": [ + { + "method": "sleep", + "params": 30 + } + ] + } + }, + { + "name": "下滑进入下一个直播间", + "android": { + "actions": [ + { + "method": "swipe", + "params": [ + 0.5, + 0.7, + 0.5, + 0.1 + ], + "identifier": "slide_in_live_new" + }, + { + "method": "sleep", + "params": 30 + } + ] + } + }, + { + "name": "返回主界面,并打开本地时间戳", + "android": { + "actions": [ + { + "method": "app_terminate", + "params": "com.ss.android.ugc.aweme.lite" + }, + { + "method": "home" + }, + { + "method": "swipe_to_tap_app", + "params": "local", + "max_retry_times": 5, + "offset": [ + 0, + -50 + ] }, { "method": "sleep", @@ -31,107 +227,10 @@ }, "validate": [ { - "check": "ui_foreground_app", - "assert": "equal", - "expect": "com.ss.android.ugc.aweme", - "msg": "app [com.ss.android.ugc.aweme] should be in foreground" - } - ] - }, - { - "name": "处理青少年弹窗", - "android": { - "actions": [ - { - "method": "tap_ocr", - "params": "我知道了", - "options": { - "ignore_NotFoundError": true - } - } - ] - } - }, - { - "name": "滑动 Feed 3 次,随机间隔 0-5s", - "android": { - "actions": [ - { - "method": "swipe", - "params": "up", - "options": {} - }, - { - "method": "sleep_random", - "params": [ - 0, - 5 - ] - } - ] - }, - "loops": 3 - }, - { - "name": "滑动 Feed 1 次,随机间隔 5-10s", - "android": { - "actions": [ - { - "method": "swipe", - "params": "up", - "options": {} - }, - { - "method": "sleep_random", - "params": [ - 5, - 10 - ] - } - ] - }, - "loops": 1 - }, - { - "name": "滑动 Feed 10 次,70% 随机间隔 0-5s,30% 随机间隔 5-10s", - "android": { - "actions": [ - { - "method": "swipe", - "params": "up", - "options": {} - }, - { - "method": "sleep_random", - "params": [ - 0, - 5, - 0.7, - 5, - 10, - 0.3 - ] - } - ] - }, - "loops": 10 - }, - { - "name": "exit", - "android": { - "actions": [ - { - "method": "app_terminate", - "params": "com.ss.android.ugc.aweme" - } - ] - }, - "validate": [ - { - "check": "ui_foreground_app", - "assert": "not_equal", - "expect": "com.ss.android.ugc.aweme", - "msg": "app [com.ss.android.ugc.aweme] should not be in foreground" + "check": "ui_ocr", + "assert": "exists", + "expect": "17", + "msg": "打开本地时间戳失败" } ] } diff --git a/hrp/internal/env/env.go b/hrp/internal/env/env.go index 8bb808bf..5168990d 100644 --- a/hrp/internal/env/env.go +++ b/hrp/internal/env/env.go @@ -22,15 +22,18 @@ var ( const ( ResultsDirName = "results" ScreenshotsDirName = "screenshots" + ActionLogDireName = "action_log" ) var ( - RootDir string - ResultsDir string - ResultsPath string - ScreenShotsPath string - StartTime = time.Now() - StartTimeStr = StartTime.Format("20060102150405") + RootDir string + ResultsDir string + ResultsPath string + ScreenShotsPath string + StartTime = time.Now() + StartTimeStr = StartTime.Format("20060102150405") + ActionLogFilePath string + DeviceActionLogFilePath string ) func init() { @@ -43,4 +46,6 @@ func init() { ResultsDir = filepath.Join(ResultsDirName, StartTimeStr) ResultsPath = filepath.Join(RootDir, ResultsDir) ScreenShotsPath = filepath.Join(ResultsPath, ScreenshotsDirName) + ActionLogFilePath = filepath.Join(ResultsDir, ActionLogDireName) + DeviceActionLogFilePath = "/sdcard/Android/data/io.appium.uiautomator2.server/files/hodor" } diff --git a/hrp/pkg/uixt/android_adb_driver.go b/hrp/pkg/uixt/android_adb_driver.go index 64b4d94e..2fc80a57 100644 --- a/hrp/pkg/uixt/android_adb_driver.go +++ b/hrp/pkg/uixt/android_adb_driver.go @@ -3,6 +3,9 @@ package uixt import ( "bytes" "fmt" + "io/fs" + "io/ioutil" + "path/filepath" "strconv" "strings" "time" @@ -10,7 +13,9 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog/log" + "github.com/httprunner/funplugin/myexec" "github.com/httprunner/httprunner/v4/hrp/internal/code" + "github.com/httprunner/httprunner/v4/hrp/internal/env" "github.com/httprunner/httprunner/v4/hrp/pkg/gadb" ) @@ -448,7 +453,40 @@ func (ad *adbDriver) StopCaptureLog() (result interface{}, err error) { } content := ad.logcat.logBuffer.String() log.Info().Str("logcat content", content).Msg("display logcat content") - return ConvertPoints(content), nil + pointRes := ConvertPoints(content) + // 没有解析到打点日志,走兜底逻辑 + if len(pointRes) == 0 { + logFilePathPrefix := fmt.Sprintf("%v/data", env.ActionLogFilePath) + files := []string{} + myexec.RunCommand("adb", "pull", env.DeviceActionLogFilePath, env.ActionLogFilePath) + err = filepath.Walk(env.ActionLogFilePath, func(path string, info fs.FileInfo, err error) error { + // 只是需要日志文件 + if ok := strings.Contains(path, logFilePathPrefix); ok { + files = append(files, path) + } + return nil + }) + + // 先保持原有状态码不变,这里不return error + if err != nil { + log.Error().Err(err).Msg("read log file fail") + return pointRes, nil + } + + if len(files) != 1 { + log.Error().Err(err).Msg("log file count error") + return pointRes, nil + } + + data, err := ioutil.ReadFile(files[0]) + if err != nil { + log.Info().Msg("read File error") + return pointRes, nil + } + + pointRes = ConvertPoints(string(data)) + } + return pointRes, nil } func (ad *adbDriver) GetForegroundApp() (app AppInfo, err error) { diff --git a/hrp/runner.go b/hrp/runner.go index b68a5208..986dc931 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -18,6 +18,7 @@ import ( "github.com/gorilla/websocket" "github.com/httprunner/funplugin" + "github.com/httprunner/funplugin/myexec" "github.com/jinzhu/copier" "github.com/pkg/errors" "github.com/rs/zerolog/log" @@ -25,6 +26,7 @@ import ( "github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/code" + "github.com/httprunner/httprunner/v4/hrp/internal/env" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" "github.com/httprunner/httprunner/v4/hrp/internal/version" "github.com/httprunner/httprunner/v4/hrp/pkg/uixt" @@ -523,6 +525,11 @@ func (r *SessionRunner) Start(givenVars map[string]interface{}) error { config := r.caseRunner.testCase.Config log.Info().Str("testcase", config.Name).Msg("run testcase start") + // 安卓系统删除打点日志文件 + if r.caseRunner.testCase.Config.Android != nil { + myexec.RunCommand("adb", "-s", r.caseRunner.testCase.Config.Android[0].SerialNumber, "shell", "rm", "-r", env.DeviceActionLogFilePath) + } + // update config variables with given variables r.InitWithParameters(givenVars)