Shoe Shoe -4 years ago 126
Android Question

Actions in monkeyrunner are not reliable

Question



My application has a map-like canvas where the user can move by dragging the map around. What I'm trying to accomplish is move the map to the right of 100px and then to the left of 100px and check if the position in the center is the same.

The code is as follows:

device.drag((640, 360), (640 - 100, 360))
device.drag((640, 360), (640 + 100, 360))
# check


This doesn't reliably bring the map to the same place every time. Sometimes the device hangs or is slow and it moves few extra pixels; some other times in the last move step it goes faster, giving it momentum.

Is there any way to precisely drag the screen of a certain amount of pixels? If the device hangs or is slow it doesn't matter, as long as the movement in the end is correct.

My attempts



I've tried to tweak the third (
duration
) and fourth (
steps
) argument to no avail.




I've also tried to implement my custom drag code with:

# Touch down screen
device.touch(100, 500, MonkeyDevice.DOWN)

# Move from 100, 500 to 200, 500
for i in range(1, 11):
device.touch(100 + 10 * i, 500, MonkeyDevice.MOVE)
time.sleep(0.1)

# Extra sleep to avoid momentum
time.sleep(0.2)

# Remove finger from screen
device.touch(200, 500, MonkeyDevice.UP)


and then to the other side:

# Touch down screen
device.touch(200, 500, MonkeyDevice.DOWN)

# Move from 200, 500 to 100, 500
for i in range(1, 11):
device.touch(200 - 10 * i, 500, MonkeyDevice.MOVE)
time.sleep(0.1)

# Extra sleep to avoid momentum
time.sleep(0.2)

# Remove finger from screen
device.touch(100, 500, MonkeyDevice.UP)





In a similar fashion I've also tried to test my game pad keys with:

for _ in range(0, 10):
device.press('KEYCODE_DPAD_RIGHT', MonkeyDevice.DOWN_AND_UP)
time.sleep(0.1)

for _ in range(0, 10):
device.press('KEYCODE_DPAD_LEFT', MonkeyDevice.DOWN_AND_UP)
time.sleep(0.1)


and even then sometimes
monkeyrunner
will either skip events or not consider the up event and therefore causing a long press (which is equivalent to "keep moving on the map").

Useful references:




Answer Source

Very good question. After reading it I was also intrigued and I wonder if the problem affects AndroidViewClient/culebra too (which is more reliable).

However, as the folowing steps can tell it might be more related to the way Maps moves than the reliability of the different protocols sending envents. Also, a methond of automating the test is given, as you mentioned that you were doing a visual comparison of the results.

I think it would be of great help to share this and it may give you additional ideas to test your app.

Started by creating a test using culebra GUI.

enter image description here

Then I slightly edited the test to factor the points and add the opposite drag.

#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''
Copyright (C) 2013-2016  Diego Torres Milano
Created on 2017-03-04 by Culebra
                      __    __    __    __
                     /  \  /  \  /  \  /  \ 
____________________/  __\/  __\/  __\/  __\_____________________________
___________________/  /__/  /__/  /__/  /________________________________
                   | / \   / \   / \   / \   \___
                   |/   \_/   \_/   \_/   \    o \ 
                                           \_____/--<
@author: Diego Torres Milano
@author: Jennifer E. Swofford (ascii art snake)
'''


import re
import sys
import os


import unittest
try:
    sys.path.insert(0, os.path.join(os.environ['ANDROID_VIEW_CLIENT_HOME'], 'src'))
except:
    pass

import pkg_resources
pkg_resources.require('androidviewclient>=13.0.0')
from com.dtmilano.android.viewclient import ViewClient, CulebraTestCase
from com.dtmilano.android.uiautomator.uiautomatorhelper import UiAutomatorHelper, UiScrollable, UiObject, UiObject2

TAG = 'CULEBRA'


class CulebraTests(CulebraTestCase):

    @classmethod
    def setUpClass(cls):
        cls.kwargs1 = {'ignoreversioncheck': False, 'verbose': False, 'ignoresecuredevice': False}
        cls.kwargs2 = {'forceviewserveruse': False, 'useuiautomatorhelper': False, 'ignoreuiautomatorkilled': True, 'autodump': False, 'startviewserver': True, 'compresseddump': True}
        cls.options = {'start-activity': None, 'concertina': False, 'device-art': None, 'use-jar': False, 'multi-device': False, 'unit-test-class': True, 'save-screenshot': None, 'use-dictionary': False, 'glare': False, 'dictionary-keys-from': 'id', 'scale': 1, 'find-views-with-content-description': True, 'window': -1, 'orientation-locked': None, 'save-view-screenshots': None, 'find-views-by-id': True, 'log-actions': False, 'use-regexps': False, 'null-back-end': False, 'auto-regexps': None, 'do-not-verify-screen-dump': True, 'verbose-comments': False, 'gui': False, 'find-views-with-text': True, 'prepend-to-sys-path': False, 'install-apk': None, 'drop-shadow': False, 'output': None, 'unit-test-method': None, 'interactive': False}
        cls.sleep = 5

    def setUp(self):
        super(CulebraTests, self).setUp()

    def tearDown(self):
        super(CulebraTests, self).tearDown()

    def preconditions(self):
        if not super(CulebraTests, self).preconditions():
            return False
        return True

    def testSomething(self):
        if not self.preconditions():
            self.fail('Preconditions failed')

        _s = CulebraTests.sleep
        _v = CulebraTests.verbose

        d = '/tmp/'

        p = (377.14, 380.86)
        q = (175.14, 380.86)

        self.vc.writeImageToFile(d + 'map-start.png')

        # Each step execution is throttled to 5ms per step
        # So for a 400 steps, the swipe will take about 2 second to complete
        steps = 400
        duration = 2000
        # Let's give some extra delay.
        sleep = 3

        for n in range(10):
            print n
            self.device.dragDip(p, q, duration, steps)
            self.vc.sleep(sleep)
            self.device.dragDip(q, p, duration, steps)
            self.vc.sleep(sleep)

        self.vc.writeImageToFile(d + 'map-finish.png')

        self.device.compare(d + 'map-finish.png', d + 'map-start.png', d + 'map-compare.png')

if __name__ == '__main__':
    CulebraTests.main()

Once run it, these are the results before and after the iterations

enter image description here enter image description here enter image description here

In this last image, you can see the visual comparison and it reveals there a slight movement. However, I think this might be just the way Maps do it.

I also used CulebraTester which uses a completely different backend based on UiAutomator and the same problem shows up. So I don't think is something related to drag.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download