mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-11 18:11:21 +08:00
Merge pull request #1490 from httprunner/dev-v4.3-android-log
fix: accurate adb logging with identifier
This commit is contained in:
@@ -7,8 +7,6 @@ import (
|
||||
"net"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
@@ -17,6 +15,7 @@ import (
|
||||
"github.com/rs/zerolog/log"
|
||||
|
||||
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
||||
"github.com/httprunner/httprunner/v4/hrp/internal/json"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -28,15 +27,6 @@ var (
|
||||
|
||||
const forwardToPrefix = "forward-to-"
|
||||
|
||||
const (
|
||||
regexFloat = `[0-9\.]*`
|
||||
)
|
||||
|
||||
var (
|
||||
regexCompileSwipe = regexp.MustCompile(fmt.Sprintf(`timesec=(%s)\s*startX=(%s)\s*startY=(%s)\s*endX=(%s)\s*endY=(%s)`, regexFloat, regexFloat, regexFloat, regexFloat, regexFloat)) // parse ${var} or $var
|
||||
regexCompileTap = regexp.MustCompile(fmt.Sprintf(`timesec=(%s)\s*x=(%s)\s*y=(%s)`, regexFloat, regexFloat, regexFloat)) // parse ${func1($a, $b)} // parse number
|
||||
)
|
||||
|
||||
func InitUIAClient(device *AndroidDevice) (*DriverExt, error) {
|
||||
var deviceOptions []AndroidDeviceOption
|
||||
if device.SerialNumber != "" {
|
||||
@@ -75,6 +65,7 @@ func InitUIAClient(device *AndroidDevice) (*DriverExt, error) {
|
||||
}
|
||||
}
|
||||
|
||||
driverExt.UUID = androidDevice.UUID()
|
||||
return driverExt, err
|
||||
}
|
||||
|
||||
@@ -308,43 +299,15 @@ type ExportPoint struct {
|
||||
func ConvertPoints(data string) (eps []ExportPoint) {
|
||||
lines := strings.Split(data, "\n")
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, "startX") {
|
||||
matched := regexCompileSwipe.FindStringSubmatch(line)
|
||||
if len(matched) != 6 {
|
||||
if strings.Contains(line, "ext") {
|
||||
idx := strings.Index(line, "{")
|
||||
line = line[idx:]
|
||||
p := ExportPoint{}
|
||||
err := json.Unmarshal([]byte(line), &p)
|
||||
if err != nil {
|
||||
log.Error().Msg("failed to parse point data")
|
||||
continue
|
||||
}
|
||||
start, _ := strconv.Atoi(matched[1])
|
||||
fromX, _ := strconv.ParseFloat(matched[2], 64)
|
||||
fromY, _ := strconv.ParseFloat(matched[3], 64)
|
||||
toX, _ := strconv.ParseFloat(matched[4], 64)
|
||||
toY, _ := strconv.ParseFloat(matched[5], 64)
|
||||
p := ExportPoint{
|
||||
Start: start,
|
||||
End: start,
|
||||
From: []float64{fromX, fromY},
|
||||
To: []float64{toX, toY},
|
||||
Operation: "Gtf-Drag",
|
||||
Ext: "",
|
||||
}
|
||||
eps = append(eps, p)
|
||||
} else if strings.Contains(line, "x=") {
|
||||
matched := regexCompileTap.FindStringSubmatch(line)
|
||||
if len(matched) != 4 {
|
||||
log.Error().Msg("failed to parse point data")
|
||||
continue
|
||||
}
|
||||
start, _ := strconv.Atoi(matched[1])
|
||||
x, _ := strconv.ParseFloat(matched[2], 64)
|
||||
y, _ := strconv.ParseFloat(matched[3], 64)
|
||||
p := ExportPoint{
|
||||
Start: start,
|
||||
End: start,
|
||||
From: []float64{x, y},
|
||||
To: []float64{x, y},
|
||||
Operation: "Gtf-Tap",
|
||||
Ext: "",
|
||||
}
|
||||
eps = append(eps, p)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
)
|
||||
|
||||
func TestConvertPoints(t *testing.T) {
|
||||
data := "09-29 15:02:08.379 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434928378\tstartX=720.000000\tstartY=1462.000000\tendX=1296.000000\tendY=1462.000000\n09-29 15:02:09.433 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434929432\tstartX=720.000000\tstartY=1462.000000\tendX=1296.000000\tendY=1462.000000\n09-29 15:02:10.452 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434930452\tstartX=720.000000\tstartY=1462.000000\tendX=1296.000000\tendY=1462.000000\n09-29 15:02:11.451 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434931450\tstartX=720.000000\tstartY=1462.000000\tendX=1296.000000\tendY=1462.000000\n09-29 15:02:12.491 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434932489\tstartX=720.000000\tstartY=1462.000000\tendX=1296.000000\tendY=1462.000000\n09-29 15:02:16.028 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434936027\tstartX=720.000000\tstartY=1462.000000\tendX=144.000000\tendY=1462.000000\n09-29 15:02:21.424 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434941423\tstartX=720.000000\tstartY=1462.000000\tendX=144.000000\tendY=1462.000000\n09-29 15:02:27.923 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434947922\tstartX=720.000000\tstartY=1462.000000\tendX=144.000000\tendY=1462.000000\n09-29 15:02:33.628 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434953628\tstartX=720.000000\tstartY=1462.000000\tendX=144.000000\tendY=1462.000000\n09-29 15:02:39.347 I/iesqaMonitor( 9938): [tap]\ttimesec=1664434959347\tx=1259.5y=1868.5"
|
||||
data := "10-09 20:16:48.216 I/iesqaMonitor(17845): {\"duration\":0,\"end\":1665317808206,\"ext\":\"输入\",\"from\":{\"x\":0.0,\"y\":0.0},\"operation\":\"Gtf-SendKeys\",\"run_time\":627,\"start\":1665317807579,\"start_first\":0,\"start_last\":0,\"to\":{\"x\":0.0,\"y\":0.0}}\n10-09 20:18:22.899 I/iesqaMonitor(17845): {\"duration\":0,\"end\":1665317902898,\"ext\":\"进入直播间\",\"from\":{\"x\":717.0,\"y\":2117.5},\"operation\":\"Gtf-Tap\",\"run_time\":121,\"start\":1665317902777,\"start_first\":0,\"start_last\":0,\"to\":{\"x\":717.0,\"y\":2117.5}}\n10-09 20:18:32.063 I/iesqaMonitor(17845): {\"duration\":0,\"end\":1665317912062,\"ext\":\"第一次上划\",\"from\":{\"x\":1437.0,\"y\":2409.9},\"operation\":\"Gtf-Swipe\",\"run_time\":32,\"start\":1665317912030,\"start_first\":0,\"start_last\":0,\"to\":{\"x\":1437.0,\"y\":2409.9}}"
|
||||
eps := ConvertPoints(data)
|
||||
if len(eps) != 10 {
|
||||
if len(eps) != 3 {
|
||||
t.Fatal()
|
||||
}
|
||||
jsons, _ := json.Marshal(eps)
|
||||
|
||||
@@ -482,7 +482,7 @@ func (ud *uiaDriver) AppAuthReset(resource ProtectedResource) (err error) {
|
||||
}
|
||||
|
||||
func (ud *uiaDriver) Tap(x, y int, options ...DataOption) error {
|
||||
return ud.TapFloat(float64(x), float64(y))
|
||||
return ud.TapFloat(float64(x), float64(y), options...)
|
||||
}
|
||||
|
||||
func (ud *uiaDriver) TapFloat(x, y float64, options ...DataOption) (err error) {
|
||||
@@ -491,6 +491,11 @@ func (ud *uiaDriver) TapFloat(x, y float64, options ...DataOption) (err error) {
|
||||
"x": x,
|
||||
"y": y,
|
||||
}
|
||||
// append options in post data for extra uiautomator configurations
|
||||
for _, option := range options {
|
||||
option(data)
|
||||
}
|
||||
|
||||
_, err = ud.httpPOST(data, "/session", ud.sessionId, "appium/tap")
|
||||
return
|
||||
}
|
||||
@@ -546,8 +551,7 @@ func (ud *uiaDriver) DragFloat(fromX, fromY, toX, toY float64, options ...DataOp
|
||||
"endY": toY,
|
||||
}
|
||||
|
||||
// append options in post data for extra WDA configurations
|
||||
// e.g. use WithPressDuration to set pressForDuration
|
||||
// append options in post data for extra uiautomator configurations
|
||||
for _, option := range options {
|
||||
option(data)
|
||||
}
|
||||
@@ -559,17 +563,23 @@ func (ud *uiaDriver) DragFloat(fromX, fromY, toX, toY float64, options ...DataOp
|
||||
return ud._drag(data)
|
||||
}
|
||||
|
||||
func (ud *uiaDriver) _swipe(startX, startY, endX, endY interface{}, steps int, elementID ...string) (err error) {
|
||||
func (ud *uiaDriver) _swipe(startX, startY, endX, endY interface{}, options ...DataOption) (err error) {
|
||||
// register(postHandler, new Swipe("/wd/hub/session/:sessionId/touch/perform"))
|
||||
data := map[string]interface{}{
|
||||
"startX": startX,
|
||||
"startY": startY,
|
||||
"endX": endX,
|
||||
"endY": endY,
|
||||
"steps": steps,
|
||||
}
|
||||
if len(elementID) != 0 {
|
||||
data["elementId"] = elementID[0]
|
||||
|
||||
// append options in post data for extra uiautomator configurations
|
||||
// e.g. use WithPressDuration to set pressForDuration
|
||||
for _, option := range options {
|
||||
option(data)
|
||||
}
|
||||
|
||||
if _, ok := data["steps"]; !ok {
|
||||
data["steps"] = 12 // default steps
|
||||
}
|
||||
_, err = ud.httpPOST(data, "/session", ud.sessionId, "touch/perform")
|
||||
return
|
||||
@@ -580,23 +590,12 @@ func (ud *uiaDriver) _swipe(startX, startY, endX, endY interface{}, steps int, e
|
||||
// per step. So for a 100 steps, the swipe will take about 1/2 second to complete.
|
||||
// `steps` is the number of move steps sent to the system
|
||||
func (ud *uiaDriver) Swipe(fromX, fromY, toX, toY int, options ...DataOption) error {
|
||||
options = append(options, WithPressDuration(0))
|
||||
options = append(options, WithSteps(12))
|
||||
return ud.SwipeFloat(float64(fromX), float64(fromY), float64(toX), float64(toY), options...)
|
||||
}
|
||||
|
||||
func (ud *uiaDriver) SwipeFloat(fromX, fromY, toX, toY float64, options ...DataOption) error {
|
||||
data := map[string]interface{}{}
|
||||
// append options in post data for extra WDA configurations
|
||||
// e.g. use WithPressDuration to set pressForDuration
|
||||
for _, option := range options {
|
||||
option(data)
|
||||
}
|
||||
|
||||
if _, ok := data["steps"]; !ok {
|
||||
data["steps"] = 12 // default steps
|
||||
}
|
||||
|
||||
return ud._swipe(fromX, fromY, toX, toY, data["steps"].(int))
|
||||
return ud._swipe(fromX, fromY, toX, toY, options...)
|
||||
}
|
||||
|
||||
func (ud *uiaDriver) ForceTouch(x, y int, pressure float64, second ...float64) error {
|
||||
@@ -671,8 +670,7 @@ func (ud *uiaDriver) SendKeys(text string, options ...DataOption) (err error) {
|
||||
data := map[string]interface{}{
|
||||
"text": text,
|
||||
}
|
||||
// append options in post data for extra WDA configurations
|
||||
// e.g. use WithPressDuration to set pressForDuration
|
||||
// append options in post data for extra uiautomator configurations
|
||||
for _, option := range options {
|
||||
option(data)
|
||||
}
|
||||
@@ -690,7 +688,7 @@ func (ud *uiaDriver) Input(text string, options ...DataOption) (err error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return element.SendKeys(text)
|
||||
return element.SendKeys(text, options...)
|
||||
}
|
||||
|
||||
func (ud *uiaDriver) KeyboardDismiss(keyNames ...string) (err error) {
|
||||
|
||||
@@ -21,16 +21,22 @@ func (ue uiaElement) Click() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (ue uiaElement) SendKeys(text string, isReplace ...int) (err error) {
|
||||
if len(isReplace) == 0 {
|
||||
isReplace = []int{1}
|
||||
}
|
||||
func (ue uiaElement) SendKeys(text string, options ...DataOption) (err error) {
|
||||
// register(postHandler, new SendKeysToElement("/wd/hub/session/:sessionId/element/:id/value"))
|
||||
// https://github.com/appium/appium-uiutomator2-server/blob/master/app/src/main/java/io/appium/uiutomator2/handler/SendKeysToElement.java#L76-L85
|
||||
data := map[string]interface{}{
|
||||
"text": text,
|
||||
"replace": isReplace[0] == 1,
|
||||
"text": text,
|
||||
}
|
||||
|
||||
// append options in post data for extra uiautomator configurations
|
||||
for _, option := range options {
|
||||
option(data)
|
||||
}
|
||||
|
||||
if _, ok := data["isReplace"]; !ok {
|
||||
data["isReplace"] = true // default true
|
||||
}
|
||||
|
||||
_, err = ue.parent.httpPOST(data, "/session", ue.parent.sessionId, "/element", ue.id, "/value")
|
||||
return
|
||||
}
|
||||
@@ -105,7 +111,11 @@ func (ue uiaElement) Swipe(fromX, fromY, toX, toY int) error {
|
||||
}
|
||||
|
||||
func (ue uiaElement) SwipeFloat(fromX, fromY, toX, toY float64) error {
|
||||
return ue.parent._swipe(fromX, fromY, toX, toY, 12, ue.id)
|
||||
options := []DataOption{
|
||||
WithSteps(12),
|
||||
WithCustomOption("elementId", ue.id),
|
||||
}
|
||||
return ue.parent._swipe(fromX, fromY, toX, toY, options...)
|
||||
}
|
||||
|
||||
func (ue uiaElement) SwipeDirection(direction Direction, velocity ...float64) (err error) {
|
||||
|
||||
@@ -788,6 +788,12 @@ func WithPressDuration(duraion float64) DataOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithSteps(steps int) DataOption {
|
||||
return func(data map[string]interface{}) {
|
||||
data["steps"] = steps
|
||||
}
|
||||
}
|
||||
|
||||
func WithFrequency(frequency int) DataOption {
|
||||
return func(data map[string]interface{}) {
|
||||
data["frequency"] = frequency
|
||||
@@ -1003,7 +1009,7 @@ type WebElement interface {
|
||||
// SendKeys Types a text into element. It will try to activate keyboard on element,
|
||||
// if element has no keyboard focus.
|
||||
// frequency: Frequency of typing (letters per sec). The default value is 60
|
||||
SendKeys(text string, frequency ...int) error
|
||||
SendKeys(text string, options ...DataOption) error
|
||||
// Clear Clears text on element. It will try to activate keyboard on element,
|
||||
// if element has no keyboard focus.
|
||||
Clear() error
|
||||
|
||||
@@ -25,13 +25,20 @@ func (we wdaElement) Click() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (we wdaElement) SendKeys(text string, frequency ...int) (err error) {
|
||||
func (we wdaElement) SendKeys(text string, options ...DataOption) (err error) {
|
||||
// [[FBRoute POST:@"/element/:uuid/value"] respondWithTarget:self action:@selector(handleSetValue:)]
|
||||
data := map[string]interface{}{"value": strings.Split(text, "")}
|
||||
if len(frequency) == 0 || frequency[0] <= 0 {
|
||||
frequency = []int{60}
|
||||
data := map[string]interface{}{
|
||||
"value": strings.Split(text, ""),
|
||||
}
|
||||
data["frequency"] = frequency[0]
|
||||
// append options in post data for extra uiautomator configurations
|
||||
for _, option := range options {
|
||||
option(data)
|
||||
}
|
||||
|
||||
if _, ok := data["frequency"]; !ok {
|
||||
data["frequency"] = 60
|
||||
}
|
||||
|
||||
_, err = we.parent.httpPOST(data, "/session", we.parent.sessionId, "/element", we.id, "/value")
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user