mirror of
https://github.com/httprunner/httprunner.git
synced 2026-09-05 23:51:25 +08:00
feat: add bilibili ios script
This commit is contained in:
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"name": "run ui test on bili ios",
|
||||||
|
"variables": {
|
||||||
|
"RunTimes": 3,
|
||||||
|
"UDID": "${ENV(UDID)}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"teststeps": [
|
||||||
|
{
|
||||||
|
"name": "run bili ios",
|
||||||
|
"shell": {
|
||||||
|
"string": "bili_ios",
|
||||||
|
"expect_exit_code": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/pkg/uixt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
serial string
|
||||||
|
runTimes int
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
serial = os.Getenv("UDID")
|
||||||
|
numStr := os.Getenv("RunTimes")
|
||||||
|
defaultNum := 20
|
||||||
|
|
||||||
|
var err error
|
||||||
|
runTimes, err = strconv.Atoi(numStr)
|
||||||
|
if err != nil {
|
||||||
|
runTimes = defaultNum
|
||||||
|
}
|
||||||
|
fmt.Printf("=== start running cases, serial=%s, runTimes=%d ===\n", serial, runTimes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func launchAppDriver(pkgName string) (driver *uixt.DriverExt, err error) {
|
||||||
|
device, _ := uixt.NewIOSDevice(uixt.WithUDID(serial))
|
||||||
|
driver, err = device.NewDriver()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//_, err = driver.Driver.AppTerminate(pkgName)
|
||||||
|
//if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//err = driver.Driver.Homescreen()
|
||||||
|
//if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//err = driver.Driver.AppLaunch(pkgName)
|
||||||
|
//if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
|
||||||
|
time.Sleep(15 * time.Second)
|
||||||
|
|
||||||
|
// 处理弹窗
|
||||||
|
err = driver.ClosePopupsHandler()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 进入推荐页
|
||||||
|
err = driver.TapByOCR("推荐", uixt.WithScope(0, 0, 1, 0.3))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return driver, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func watchVideo(driver *uixt.DriverExt) (err error) {
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
err = driver.SwipeRelative(0.7, 0.7, 0.7, 0.2)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
// 点击进入某视频
|
||||||
|
err = driver.TapXY(0.3, 0.5)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
// 点击播放区域,展现横屏图标
|
||||||
|
err = driver.TapXY(0.5, 0.1)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
|
||||||
|
// 切换横屏
|
||||||
|
err = driver.TapByUIDetection(
|
||||||
|
uixt.WithScreenShotUITypes("fullScreen"))
|
||||||
|
if err != nil {
|
||||||
|
// 未找到横屏图标,该页面可能不是横版视频(直播|广告|Feed)
|
||||||
|
// 退出回到推荐页
|
||||||
|
driver.Driver.PressBack()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 观播 10s
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
|
||||||
|
// 返回视频页面
|
||||||
|
err = driver.Driver.PressBack()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
// 返回推荐页
|
||||||
|
err = driver.Driver.PressBack()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// build shell command
|
||||||
|
// go build -o bili_android examples/uitest/bilibili/cli.go
|
||||||
|
func main() {
|
||||||
|
driver, err := launchAppDriver("tv.danmaku.bilianime")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重复采集 XX 次
|
||||||
|
for i := 0; i < runTimes; i++ {
|
||||||
|
err = watchVideo(driver)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -80,4 +80,4 @@ require (
|
|||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
// replace github.com/httprunner/funplugin => ../funplugin
|
replace github.com/httprunner/funplugin v0.5.4 => /Users/bytedance/go/src/github.com/httprunner/funplugin
|
||||||
|
|||||||
@@ -172,8 +172,6 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
|||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||||
github.com/httprunner/funplugin v0.5.4 h1:hlfNGcYw2Rv2Mdp1l2S1R6ufwzKgpB9lheFvAxI0LfM=
|
|
||||||
github.com/httprunner/funplugin v0.5.4/go.mod h1:YZzBBSOSdLZEpHZz0P2E5SOQ+o1+Fbn30oWS4RGHBz0=
|
|
||||||
github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs=
|
github.com/hybridgroup/mjpeg v0.0.0-20140228234708-4680f319790e/go.mod h1:eagM805MRKrioHYuU7iKLUyFPVKqVV6um5DAvCkUtXs=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v4.3.8.202404161520
|
v4.3.8.202405262130
|
||||||
@@ -114,7 +114,12 @@ func (vc *VideoCrawler) isTargetAchieved() bool {
|
|||||||
|
|
||||||
func (vc *VideoCrawler) exitLiveRoom() error {
|
func (vc *VideoCrawler) exitLiveRoom() error {
|
||||||
log.Info().Msg("press back to exit live room")
|
log.Info().Msg("press back to exit live room")
|
||||||
return vc.driverExt.Driver.PressBack()
|
err := vc.driverExt.Driver.PressBack()
|
||||||
|
time.Sleep(time.Duration(3) * time.Second)
|
||||||
|
if vc.driverExt.TapByOCR("退出直播间") == nil {
|
||||||
|
log.Info().Msg("clicked the button to exit the live room successfully")
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -231,6 +236,7 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) {
|
|||||||
log.Error().Err(err).Msg("tap live video failed")
|
log.Error().Err(err).Msg("tap live video failed")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
currentVideo.Type = VideoType_Live
|
||||||
} else {
|
} else {
|
||||||
// skip entering live room
|
// skip entering live room
|
||||||
// only mock simulation play duration
|
// only mock simulation play duration
|
||||||
@@ -282,7 +288,8 @@ func (dExt *DriverExt) VideoCrawler(configs *VideoCrawlerConfigs) (err error) {
|
|||||||
exitLive = true
|
exitLive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isFeed) && exitLive && currentVideo.Type == VideoType_Live {
|
// isFeed:通过预览流进入内流失败的情况下,防止使用退出直播间逻辑,影响:首次进入内流,至少会消费两个直播间才能退出
|
||||||
|
if !isFeed && exitLive && currentVideo.Type == VideoType_Live {
|
||||||
err = crawler.exitLiveRoom()
|
err = crawler.exitLiveRoom()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, code.TimeoutError) || errors.Is(err, code.InterruptError) {
|
if errors.Is(err, code.TimeoutError) || errors.Is(err, code.InterruptError) {
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/httprunner/httprunner/v4/hrp/internal/sdk"
|
||||||
|
|
||||||
"github.com/httprunner/funplugin"
|
"github.com/httprunner/funplugin"
|
||||||
"github.com/httprunner/funplugin/myexec"
|
"github.com/httprunner/funplugin/myexec"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -13,7 +15,6 @@ import (
|
|||||||
|
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
"github.com/httprunner/httprunner/v4/hrp/internal/code"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/env"
|
"github.com/httprunner/httprunner/v4/hrp/internal/env"
|
||||||
"github.com/httprunner/httprunner/v4/hrp/internal/sdk"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|||||||
+8
-1
@@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/httprunner/funplugin"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
@@ -17,7 +18,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/httprunner/funplugin"
|
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
@@ -240,6 +240,13 @@ func (r *HRPRunner) Run(testcases ...ITestCase) (err error) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if caseRunner.parsedConfig.PluginSetting != nil {
|
||||||
|
if p, ok := pluginMap.Load(caseRunner.parsedConfig.PluginSetting.Path); ok {
|
||||||
|
log.Info().Msg(fmt.Sprintf("starting to keep live, path: %v, address: %v", caseRunner.parsedConfig.PluginSetting.Path, p))
|
||||||
|
go p.(funplugin.IPlugin).StartHeartbeat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for it := caseRunner.parametersIterator; it.HasNext(); {
|
for it := caseRunner.parametersIterator; it.HasNext(); {
|
||||||
// case runner can run multiple times with different parameters
|
// case runner can run multiple times with different parameters
|
||||||
// each run has its own session runner
|
// each run has its own session runner
|
||||||
|
|||||||
Reference in New Issue
Block a user