mirror of
https://github.com/httprunner/httprunner.git
synced 2026-06-02 22:39:42 +08:00
Merge pull request #1582 from httprunner/random_swipe
feat: random swipe with weight for multiple time ranges
This commit is contained in:
@@ -1,5 +1,15 @@
|
|||||||
# Release History
|
# Release History
|
||||||
|
|
||||||
|
## v4.3.3 (2023-04-11)
|
||||||
|
|
||||||
|
**go version**
|
||||||
|
|
||||||
|
- feat: add `sleep_random` to sleep random seconds, with weight for multiple time ranges
|
||||||
|
- feat: input text with adb
|
||||||
|
- fix: adb driver for TapFloat
|
||||||
|
- fix: stop logcat only when enabled
|
||||||
|
- fix: do not fail case when kill logcat error
|
||||||
|
|
||||||
## v4.3.2 (2022-12-26)
|
## v4.3.2 (2022-12-26)
|
||||||
|
|
||||||
**go version**
|
**go version**
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "滑动 Feed 35 次,随机间隔 0-20s",
|
"name": "滑动 Feed 3 次,随机间隔 0-5s",
|
||||||
"android": {
|
"android": {
|
||||||
"actions": [
|
"actions": [
|
||||||
{
|
{
|
||||||
@@ -54,15 +54,15 @@
|
|||||||
"method": "sleep_random",
|
"method": "sleep_random",
|
||||||
"params": [
|
"params": [
|
||||||
0,
|
0,
|
||||||
20
|
5
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"loops": 35
|
"loops": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "滑动 Feed 15 次,随机间隔 15-50s",
|
"name": "滑动 Feed 1 次,随机间隔 5-10s",
|
||||||
"android": {
|
"android": {
|
||||||
"actions": [
|
"actions": [
|
||||||
{
|
{
|
||||||
@@ -72,13 +72,36 @@
|
|||||||
{
|
{
|
||||||
"method": "sleep_random",
|
"method": "sleep_random",
|
||||||
"params": [
|
"params": [
|
||||||
15,
|
5,
|
||||||
50
|
10
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"loops": 15
|
"loops": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "滑动 Feed 10 次,70% 随机间隔 0-5s,30% 随机间隔 5-10s",
|
||||||
|
"android": {
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"method": "swipe",
|
||||||
|
"params": "up"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"method": "sleep_random",
|
||||||
|
"params": [
|
||||||
|
0,
|
||||||
|
5,
|
||||||
|
0.7,
|
||||||
|
5,
|
||||||
|
10,
|
||||||
|
0.3
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"loops": 10
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,16 +25,21 @@ func TestAndroidDouyinFeedTest(t *testing.T) {
|
|||||||
hrp.NewStep("处理青少年弹窗").
|
hrp.NewStep("处理青少年弹窗").
|
||||||
Android().
|
Android().
|
||||||
TapByOCR("我知道了", uixt.WithIgnoreNotFoundError(true)),
|
TapByOCR("我知道了", uixt.WithIgnoreNotFoundError(true)),
|
||||||
hrp.NewStep("滑动 Feed 35 次,随机间隔 0-20s").
|
hrp.NewStep("滑动 Feed 3 次,随机间隔 0-5s").
|
||||||
Loop(35).
|
Loop(3).
|
||||||
Android().
|
Android().
|
||||||
SwipeUp().
|
SwipeUp().
|
||||||
SleepRandom(0, 20),
|
SleepRandom(0, 5),
|
||||||
hrp.NewStep("滑动 Feed 15 次,随机间隔 15-50s").
|
hrp.NewStep("滑动 Feed 1 次,随机间隔 5-10s").
|
||||||
Loop(15).
|
Loop(1).
|
||||||
Android().
|
Android().
|
||||||
SwipeUp().
|
SwipeUp().
|
||||||
SleepRandom(15, 50),
|
SleepRandom(5, 10),
|
||||||
|
hrp.NewStep("滑动 Feed 10 次,70% 随机间隔 0-5s,30% 随机间隔 5-10s").
|
||||||
|
Loop(10).
|
||||||
|
Android().
|
||||||
|
SwipeUp().
|
||||||
|
SleepRandom(0, 5, 0.7, 5, 10, 0.3),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
v4.3.2
|
v4.3.3
|
||||||
@@ -348,6 +348,19 @@ func (dExt *DriverExt) IsImageExist(text string) bool {
|
|||||||
|
|
||||||
var errActionNotImplemented = errors.New("UI action not implemented")
|
var errActionNotImplemented = errors.New("UI action not implemented")
|
||||||
|
|
||||||
|
func convertToFloat64(val interface{}) (float64, error) {
|
||||||
|
switch v := val.(type) {
|
||||||
|
case float64:
|
||||||
|
return v, nil
|
||||||
|
case int:
|
||||||
|
return float64(v), nil
|
||||||
|
case int64:
|
||||||
|
return float64(v), nil
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("invalid type for conversion to float64: %T, value: %+v", val, val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (dExt *DriverExt) DoAction(action MobileAction) error {
|
func (dExt *DriverExt) DoAction(action MobileAction) error {
|
||||||
log.Info().Str("method", string(action.Method)).Interface("params", action.Params).Msg("start UI action")
|
log.Info().Str("method", string(action.Method)).Interface("params", action.Params).Msg("start UI action")
|
||||||
|
|
||||||
@@ -609,24 +622,54 @@ func (dExt *DriverExt) DoAction(action MobileAction) error {
|
|||||||
}
|
}
|
||||||
return fmt.Errorf("invalid sleep params: %v(%T)", action.Params, action.Params)
|
return fmt.Errorf("invalid sleep params: %v(%T)", action.Params, action.Params)
|
||||||
case CtlSleepRandom:
|
case CtlSleepRandom:
|
||||||
if params, ok := action.Params.([]interface{}); ok && len(params) == 2 {
|
params, ok := action.Params.([]interface{})
|
||||||
var a, b float64
|
if !ok {
|
||||||
if v, ok := params[0].(float64); ok {
|
return fmt.Errorf("invalid sleep random params: %v(%T)", action.Params, action.Params)
|
||||||
a = v
|
}
|
||||||
} else if v, ok := params[0].(int64); ok {
|
// append default weight 1
|
||||||
a = float64(v)
|
if len(params) == 2 {
|
||||||
|
params = append(params, 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
var sections []struct {
|
||||||
|
min, max, weight float64
|
||||||
|
}
|
||||||
|
totalProb := 0.0
|
||||||
|
for i := 0; i+3 <= len(params); i += 3 {
|
||||||
|
min, err := convertToFloat64(params[i])
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "invalid minimum time: %v", params[i])
|
||||||
}
|
}
|
||||||
if v, ok := params[1].(float64); ok {
|
max, err := convertToFloat64(params[i+1])
|
||||||
b = v
|
if err != nil {
|
||||||
} else if v, ok := params[1].(int64); ok {
|
return errors.Wrapf(err, "invalid maximum time: %v", params[i+1])
|
||||||
b = float64(v)
|
|
||||||
}
|
}
|
||||||
n := a + rand.Float64()*(b-a)
|
weight, err := convertToFloat64(params[i+2])
|
||||||
log.Info().Float64("duration", n).Msg("sleep random seconds")
|
if err != nil {
|
||||||
time.Sleep(time.Duration(n*1000) * time.Millisecond)
|
return errors.Wrapf(err, "invalid weight value: %v", params[i+2])
|
||||||
|
}
|
||||||
|
totalProb += weight
|
||||||
|
sections = append(sections,
|
||||||
|
struct{ min, max, weight float64 }{min, max, weight},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalProb == 0 {
|
||||||
|
log.Warn().Msg("total weight is 0, skip sleep")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid sleep random params: %v(%T)", action.Params, action.Params)
|
|
||||||
|
r := rand.Float64()
|
||||||
|
accProb := 0.0
|
||||||
|
for _, s := range sections {
|
||||||
|
accProb += s.weight / totalProb
|
||||||
|
if r < accProb {
|
||||||
|
n := s.min + rand.Float64()*(s.max-s.min)
|
||||||
|
log.Info().Float64("duration", n).Msg("sleep random seconds")
|
||||||
|
time.Sleep(time.Duration(n*1000) * time.Millisecond)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
case CtlScreenShot:
|
case CtlScreenShot:
|
||||||
// take snapshot
|
// take snapshot
|
||||||
log.Info().Msg("take snapshot for current screen")
|
log.Info().Msg("take snapshot for current screen")
|
||||||
|
|||||||
@@ -281,10 +281,14 @@ func (s *StepMobile) Sleep(n float64) *StepMobile {
|
|||||||
return &StepMobile{step: s.step}
|
return &StepMobile{step: s.step}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StepMobile) SleepRandom(a, b float64) *StepMobile {
|
// SleepRandom specify random sleeping seconds after last action
|
||||||
|
// params have two different kinds:
|
||||||
|
// 1. [min, max] : min and max are float64 time range boudaries
|
||||||
|
// 2. [min1, max1, weight1, min2, max2, weight2, ...] : weight is the probability of the time range
|
||||||
|
func (s *StepMobile) SleepRandom(params ...float64) *StepMobile {
|
||||||
s.mobileStep().Actions = append(s.mobileStep().Actions, uixt.MobileAction{
|
s.mobileStep().Actions = append(s.mobileStep().Actions, uixt.MobileAction{
|
||||||
Method: uixt.CtlSleepRandom,
|
Method: uixt.CtlSleepRandom,
|
||||||
Params: []float64{a, b},
|
Params: params,
|
||||||
})
|
})
|
||||||
return &StepMobile{step: s.step}
|
return &StepMobile{step: s.step}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user