Python wrapper of Android uiautomator test tool.

Related tags

Testinguiautomator
Overview

uiautomator

Join the chat at https://gitter.im/xiaocong/uiautomator

MIT License build Coverage Status pypi downloads

This module is a Python wrapper of Android uiautomator testing framework. It works on Android 4.1+ (API Level 16~30) simply with Android device attached via adb, no need to install anything on Android device.

from uiautomator import device as d

d.screen.on()
d(text="Clock").click()

Installation

$ pip install uiautomator

Pre-requirements

  • Install Android SDK, and set ANDROID_HOME environment to the correct path.
  • Enable ADB setting on device and connect your android device using usb with your PC.
  • Allow apps to install from unknown sources on device settings.

import uiautomator

  • If ANDROID_SERIAL is defined in environment, or there is only one device connected:

    from uiautomator import device as d
  • Speficy the serial number when retrieving the device object

    from uiautomator import Device
    
    d = Device('014E05DE0F02000E')
  • Speficy the adb server host and port running on other computer

    Although adb supports -a option since SDK 4.3, but now it has a bug on it. The only way to start adb server listenning on all interfaces instead of localhost, is adb -a -P 5037 fork-server server &

    from uiautomator import Device
    
    d = Device('014E05DE0F02000E', adb_server_host='192.168.1.68', adb_server_port=5037)

Notes: In below examples, we use d represent the android device object.

Table of Contents

Basic API Usages

Watcher introduction

Handler introduction

Selector introduction

Basic API Usages

This part show the normal actions of the device through some simple examples.

  • Retrieve the device info

    d.info

    Below is a possible result:

    { u'displayRotation': 0,
      u'displaySizeDpY': 640,
      u'displaySizeDpX': 360,
      u'currentPackageName': u'com.android.launcher',
      u'productName': u'takju',
      u'displayWidth': 720,
      u'sdkInt': 18,
      u'displayHeight': 1184,
      u'naturalOrientation': True
    }
    

Key Event Actions of the device

  • Turn on/off screen

    # Turn on screen
    d.screen.on()
    # Turn off screen
    d.screen.off()

    Alternative method is:

    # wakeup the device
    d.wakeup()
    # sleep the device, same as turning off the screen.
    d.sleep()
  • Check if the screen is on or off

    if d.screen == "on":  # of d.screen != "off"
        # do something in case of screen on
        pass
    if d.screen == "off":  # of d.screen != "on"
        # do something in case of screen off
        pass
  • Press hard/soft key

    # press home key
    d.press.home()
    # press back key
    d.press.back()
    # the normal way to press back key
    d.press("back")
    # press keycode 0x07('0') with META ALT(0x02) on
    d.press(0x07, 0x02)
  • Next keys are currently supported:

    • home
    • back
    • left
    • right
    • up
    • down
    • center
    • menu
    • search
    • enter
    • delete(or del)
    • recent(recent apps)
    • volume_up
    • volume_down
    • volume_mute
    • camera
    • power

    You can find all key code definitions at Android KeyEvent.

Gesture interaction of the device

  • Click the screen

    # click (x, y) on screen
    d.click(x, y)
  • Long click the screen

    # long click (x, y) on screen
    d.long_click(x, y)
  • Swipe

    # swipe from (sx, sy) to (ex, ey)
    d.swipe(sx, sy, ex, ey)
    # swipe from (sx, sy) to (ex, ey) with 10 steps
    d.swipe(sx, sy, ex, ey, steps=10)
  • Drag

    # drag from (sx, sy) to (ex, ey)
    d.drag(sx, sy, ex, ey)
    # drag from (sx, sy) to (ex, ey) with 10 steps
    d.drag(sx, sy, ex, ey, steps=10)

Screen Actions of the device

  • Retrieve/Set Orientation

    The possible orientation is:

    • natural or n
    • left or l
    • right or r
    • upsidedown or u (can not be set)
    # retrieve orientation, it may be "natural" or "left" or "right" or "upsidedown"
    orientation = d.orientation
    # set orientation and freeze rotation.
    # notes: "upsidedown" can not be set until Android 4.3.
    d.orientation = "l" # or "left"
    d.orientation = "r" # or "right"
    d.orientation = "n" # or "natural"
  • Freeze/Un-Freeze rotation

    # freeze rotation
    d.freeze_rotation()
    # un-freeze rotation
    d.freeze_rotation(False)
  • Take screenshot

    # take screenshot and save to local file "home.png", can not work until Android 4.2.
    d.screenshot("home.png")
  • Dump Window Hierarchy

    # dump the widown hierarchy and save to local file "hierarchy.xml"
    d.dump("hierarchy.xml")
    # or get the dumped content(unicode) from return.
    xml = d.dump()
  • Open notification or quick settings

    # open notification, can not work until Android 4.3.
    d.open.notification()
    # open quick settings, can not work until Android 4.3.
    d.open.quick_settings()
  • Wait for idle or window update

    # wait for current window to idle
    d.wait.idle()
    # wait until window update event occurs
    d.wait.update()

Watcher

You can register watcher to perform some actions when a selector can not find a match.

  • Register Watcher

    When a selector can not find a match, uiautomator will run all registered watchers.

    • Click target when conditions match
    d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait") \
                                 .click(text="Force Close")
    # d.watcher(name) ## creates a new named watcher.
    #  .when(condition)  ## the UiSelector condition of the watcher.
    #  .click(target)  ## perform click action on the target UiSelector.
    • Press key when conditions match
    d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait") \
                                 .press.back.home()
    # Alternative way to define it as below
    d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait") \
                                 .press("back", "home")
    # d.watcher(name) ## creates a new named watcher.
    #  .when(condition)  ## the UiSelector condition of the watcher.
    #  .press.<keyname>.....<keyname>.()  ## press keys one by one in sequence.
    #  Alternavie way defining key sequence is press(<keybname>, ..., <keyname>)
  • Check if the named watcher triggered

    A watcher is triggered, which means the watcher was run and all its conditions matched.

    d.watcher("watcher_name").triggered
    # true in case of the specified watcher triggered, else false
  • Remove named watcher

    # remove the watcher
    d.watcher("watcher_name").remove()
  • List all watchers

    d.watchers
    # a list of all registered wachers' names
  • Check if there is any watcher triggered

    d.watchers.triggered
    #  true in case of any watcher triggered
  • Reset all triggered watchers

    # reset all triggered watchers, after that, d.watchers.triggered will be false.
    d.watchers.reset()
  • Remvoe watchers

    # remove all registered watchers
    d.watchers.remove()
    # remove the named watcher, same as d.watcher("watcher_name").remove()
    d.watchers.remove("watcher_name")
  • Force to run all watchers

    # force to run all registered watchers
    d.watchers.run()

Handler

The functionality of handler is same as Watcher, except it is implemented ourside of Android uiautomator. The most different usage between handler and watcher is, handler can use customized callback function.

def fc_close(device):
  if device(text='Force Close').exists:
    device(text='Force Close').click()
  return True  # return True means to break the loop of handler callback functions.

# turn on the handler callback function
d.handlers.on(fc_close)

# turn off the handler callback function
d.handlers.off(fc_close)

Selector

Selector is to identify specific ui object in current window.

# To seleted the object ,text is 'Clock' and its className is 'android.widget.TextView'
d(text='Clock', className='android.widget.TextView')

Selector supports below parameters. Refer to UiSelector java doc for detailed information.

  • text, textContains, textMatches, textStartsWith
  • className, classNameMatches
  • description, descriptionContains, descriptionMatches, descriptionStartsWith
  • checkable, checked, clickable, longClickable
  • scrollable, enabled,focusable, focused, selected
  • packageName, packageNameMatches
  • resourceId, resourceIdMatches
  • index, instance

Child and sibling UI object

  • child

    # get the child or grandchild
    d(className="android.widget.ListView").child(text="Bluetooth")
  • sibling

    # get sibling or child of sibling
    d(text="Google").sibling(className="android.widget.ImageView")
  • child by text or description or instance

    # get the child match className="android.widget.LinearLayout"
    # and also it or its child or grandchild contains text "Bluetooth"
    d(className="android.widget.ListView", resourceId="android:id/list") \
     .child_by_text("Bluetooth", className="android.widget.LinearLayout")
    
    # allow scroll search to get the child
    d(className="android.widget.ListView", resourceId="android:id/list") \
     .child_by_text(
        "Bluetooth",
        allow_scroll_search=True,
        className="android.widget.LinearLayout"
      )
    • child_by_description is to find child which or which's grandchild contains the specified description, others are the same as child_by_text.

    • child_by_instance is to find child which has a child UI element anywhere within its sub hierarchy that is at the instance specified. It is performed on visible views without scrolling.

    See below links for detailed information:

    • UiScrollable, getChildByDescription, getChildByText, getChildByInstance
    • UiCollection, getChildByDescription, getChildByText, getChildByInstance

    Above methods support chained invoking, e.g. for below hierarchy

    <node index="0" text="" resource-id="android:id/list" class="android.widget.ListView" ...>
      <node index="0" text="WIRELESS & NETWORKS" resource-id="" class="android.widget.TextView" .../>
      <node index="1" text="" resource-id="" class="android.widget.LinearLayout" ...>
        <node index="1" text="" resource-id="" class="android.widget.RelativeLayout" ...>
          <node index="0" text="Wi‑Fi" resource-id="android:id/title" class="android.widget.TextView" .../>
        </node>
        <node index="2" text="ON" resource-id="com.android.settings:id/switchWidget" class="android.widget.Switch" .../>
      </node>
      ...
    </node>

    settings

    We want to click the switch at the right side of text 'Wi‑Fi' to turn on/of Wi‑Fi. As there are several switches with almost the same properties, so we can not use like d(className="android.widget.Switch") to select the ui object. Instead, we can use code below to select it.

    d(className="android.widget.ListView", resourceId="android:id/list") \
      .child_by_text("Wi‑Fi", className="android.widget.LinearLayout") \
      .child(className="android.widget.Switch") \
      .click()
  • relative position

    Also we can use the relative position methods to get the view: left, right, top, bottom.

    • d(A).left(B), means selecting B on the left side of A.
    • d(A).right(B), means selecting B on the right side of A.
    • d(A).up(B), means selecting B above A.
    • d(A).down(B), means selecting B under A.

    So for above case, we can write code alternatively:

    ## select "switch" on the right side of "Wi‑Fi"
    d(text="Wi‑Fi").right(className="android.widget.Switch").click()
  • Multiple instances

    Sometimes the screen may contain multiple views with the same e.g. text, then you will have to use "instance" properties in selector like below:

    d(text="Add new", instance=0)  # which means the first instance with text "Add new"

    However, uiautomator provides list like methods to use it.

    # get the count of views with text "Add new" on current screen
    d(text="Add new").count
    
    # same as count property
    len(d(text="Add new"))
    
    # get the instance via index
    d(text="Add new")[0]
    d(text="Add new")[1]
    ...
    
    # iterator
    for view in d(text="Add new"):
        view.info  # ...

    Notes: when you are using selector like a list, you must make sure the screen keep unchanged, else you may get ui not found error.

Get the selected ui object status and its information

  • Check if the specific ui object exists

    d(text="Settings").exists # True if exists, else False
    d.exists(text="Settings") # alias of above property.
  • Retrieve the info of the specific ui object

    d(text="Settings").info

    Below is a possible result:

    { u'contentDescription': u'',
      u'checked': False,
      u'scrollable': False,
      u'text': u'Settings',
      u'packageName': u'com.android.launcher',
      u'selected': False,
      u'enabled': True,
      u'bounds': {u'top': 385,
                  u'right': 360,
                  u'bottom': 585,
                  u'left': 200},
      u'className': u'android.widget.TextView',
      u'focused': False,
      u'focusable': True,
      u'clickable': True,
      u'chileCount': 0,
      u'longClickable': True,
      u'visibleBounds': {u'top': 385,
                         u'right': 360,
                         u'bottom': 585,
                         u'left': 200},
      u'checkable': False
    }
    
  • Set/Clear text of editable field

    d(text="Settings").clear_text()  # clear the text
    d(text="Settings").set_text("My text...")  # set the text

Perform the click action on the seleted ui object

  • Perform click on the specific ui object

    # click on the center of the specific ui object
    d(text="Settings").click()
    # click on the bottomright corner of the specific ui object
    d(text="Settings").click.bottomright()
    # click on the topleft corner of the specific ui object
    d(text="Settings").click.topleft()
    # click and wait until the new window update
    d(text="Settings").click.wait()
  • Perform long click on the specific ui object

    # long click on the center of the specific ui object
    d(text="Settings").long_click()
    # long click on the bottomright corner of the specific ui object
    d(text="Settings").long_click.bottomright()
    # long click on the topleft corner of the specific ui object
    d(text="Settings").long_click.topleft()

Gesture action for the specific ui object

  • Drag the ui object to another point or ui object

    # notes : drag can not be set until Android 4.3.
    # drag the ui object to point (x, y)
    d(text="Settings").drag.to(x, y, steps=100)
    # drag the ui object to another ui object(center)
    d(text="Settings").drag.to(text="Clock", steps=50)
  • Swipe from the center of the ui object to its edge

    Swipe supports 4 directions:

    • left
    • right
    • top
    • bottom
    d(text="Settings").swipe.right()
    d(text="Settings").swipe.left(steps=10)
    d(text="Settings").swipe.up(steps=10)
    d(text="Settings").swipe.down()
  • Two point gesture from one point to another

    d(text="Settings").gesture((sx1, sy1), (sx2, sy2)) \
                      .to((ex1, ey1), (ex2, ey2))
  • Two point gesture on the specific ui object

    Supports two gestures:

    • In, from edge to center
    • Out, from center to edge
    # notes : pinch can not be set until Android 4.3.
    # from edge to center. here is "In" not "in"
    d(text="Settings").pinch.In(percent=100, steps=10)
    # from center to edge
    d(text="Settings").pinch.Out()
  • 3 point gesture

    d().gestureM((sx1, sy1), (sx2, sy2),(sx3, sy3)) \
                      .to((ex1, ey1), (ex2, ey2),(ex3,ey3))
    d().gestureM((100,200),(300,200),(600,200),(100,600),(300,600),(600,900))
  • Wait until the specific ui object appears or gone

    # wait until the ui object appears
    d(text="Settings").wait.exists(timeout=3000)
    # wait until the ui object gone
    d(text="Settings").wait.gone(timeout=1000)
  • Perform fling on the specific ui object(scrollable)

    Possible properties:

    • horiz or vert
    • forward or backward or toBeginning or toEnd
    # fling forward(default) vertically(default) 
    d(scrollable=True).fling()
    # fling forward horizentally
    d(scrollable=True).fling.horiz.forward()
    # fling backward vertically
    d(scrollable=True).fling.vert.backward()
    # fling to beginning horizentally
    d(scrollable=True).fling.horiz.toBeginning(max_swipes=1000)
    # fling to end vertically
    d(scrollable=True).fling.toEnd()
  • Perform scroll on the specific ui object(scrollable)

    Possible properties:

    • horiz or vert
    • forward or backward or toBeginning or toEnd, or to
    # scroll forward(default) vertically(default)
    d(scrollable=True).scroll(steps=10)
    # scroll forward horizentally
    d(scrollable=True).scroll.horiz.forward(steps=100)
    # scroll backward vertically
    d(scrollable=True).scroll.vert.backward()
    # scroll to beginning horizentally
    d(scrollable=True).scroll.horiz.toBeginning(steps=100, max_swipes=1000)
    # scroll to end vertically
    d(scrollable=True).scroll.toEnd()
    # scroll forward vertically until specific ui object appears
    d(scrollable=True).scroll.to(text="Security")

Contribution

  • Fork the repo, and clone to your computer.
  • Checkout a new branch from develop branch
  • Install requirements: pip install -r requirements.txt
  • Make your changes, and update tests. Don't forget adding your name at the end of 'Contributors' section
  • Pass all tests and your code must be covered: tox.
  • Commit your changes and submit pull request to develop branch.

Contributors

Issues & Discussion

If you have any bug reports or annoyances please report them to our issue tracker at github issues.

Notes

  • Android uiautomator works on Android 4.1+, so before using it, make sure your device is Android4.1+.
  • Some methods are only working on Android 4.2/4.3, so you'd better read detailed java documentation of uiautomator before using it.
  • The module uses uiautomator-jsonrpc-server as its daemon to communicate with devices.
  • The module is only tested on python2.7/3.2/3.3/pypy.

FAQ

  • Could not start JSONRPC server: raise IOError("RPC server not started!")

    It may be caused by network, device, or environment. So when you meet the issue, please follow below steps and try to manually start the JSONRPC server.

    1. Follow steps at uiautomator-jsonrpc-server to start jsonrpc server.

    2. Check if jsonrpc server is ok:

       curl -d '{"jsonrpc":"2.0","method":"deviceInfo","id":1}' localhost:9008/jsonrpc/0
      

      If you see message like {"jsonrpc":"2.0","id":1,"result":{"currentPackageName":"android","displayHeight":1280,"displayRotation":0,"displaySizeDpX":0,"displaySizeDpY":0,"displayWidth":720,"productName":"falcon","sdkInt":17,"naturalOrientation":true}}, it means the server is up.

    3. check local python lib: python2.7/dist-packages/uiautomator/libs:

      device sdk_level < 18 should use jar. device sdk_level >= 18 use APK.
      

    If you can manually start the jsonrpc server, but your script always meets IOError("RPC server not started!"), please submit an issue at github issues.

  • Error httplib.BadStatusLine: ''

    JsonRPC server needs to access temp directory on device, but on some low tier devices, it may meet error during accessing temp files without SD-CARD attached. So if you met the error, please insert a SD-CARD and then try again.

License

MIT

Comments
  • Starting Server

    Starting Server

    Hi,

    I am newbie on Android so apologies for my question that may be dumb. I am trying to run the jsonrcp server on Android device using "adb shell uiautomator runtest uiautomator-stub.jar bundle.jar -c com.github.uiautomatorstub.Stub" but I am getting the following:-

    INSTRUMENTATION_RESULT: longMsg=Didn't find class "com.github.uiautomatorstub.Stub" on path: /system/framework/android.test.runner.jar:/system/framework/uiautomator.jar::/data/local/tmp/uiautomator-stub.jar:/data/local/tmp/bundle.jar INSTRUMENTATION_CODE: 0

    I have tried to follow all the steps on the instruction. I am not sure what I have missed. Please help, how can I solve this?

    bug 
    opened by thlengane 15
  • PY UIAutomator: Need Addition of Screenshot Watcher

    PY UIAutomator: Need Addition of Screenshot Watcher

    Hey there,

    What is the purpose of bundle.jar and uiautomator-stub.jar? If I want to change Server code, how to compile these two jars myself? P.S. I want to add Watcher to take screenshot by any testcase failure. I will add in the jsonserver code and then compile it to jar and use it uiautomator.py

    opened by gokulakv 14
  • Uiautomator events is not working when json rpc server runs in the device.

    Uiautomator events is not working when json rpc server runs in the device.

    Hi xiacong,

    "adb shell uiautomator events " is not working while executing the testcases using UIautomator. Is there any way where I can get the uiautomator events?

    Thanks Sridhar

    bug enhancement wontfix 
    opened by m-sridhar 14
  • Multiple Siblings

    Multiple Siblings

    Currently I have an object at index 0 and there are two other objects at index 1 and 2. From the first object i cannot use the sibling function to find index 2. I've tried using resourceId and class but they both return nothing. This works fine when there is only one sibling with the same method. This seems like a bug, unless I need index 1 to find index 2?

    bug 
    opened by ZeroInputCtrl 12
  • Add a callback interface for Watcher

    Add a callback interface for Watcher

    Currently, Watcher can trigger defined simple action, e.g, click when condition match. However, sometimes, we expect do more complex action. It is better provide a callback interface for watcher, thus user can define whatever customized action in a function.

    opened by jwang11 11
  • Visible Text

    Visible Text

    Hi @xiaocong

    I am a heavy user of this and here is one challenge I have discovered,

    There are certain objects on Android that have text in them but the text is not on the "text" and "contentDescription" field (see attachment). I suspect there might be more object that behaves like this one. However, there maybe a possible solution to this. I don't know complex it maybe from your side to create a function like "getvisible text".

    Here is how it can work:

    • Take a snapshot of the specified object
    • Scan through it using "ocr" like methods
    • Print out text from 'ocr"

    I know "ocr" is far from perfect but at least it will retrieve some text.

    Device Used: Galaxy S5 4.4.2

    uiautomator_screenshot

    enhancement 
    opened by thlengane 9
  • IOError: RPC server not started!

    IOError: RPC server not started!

    Hi: I had problems to start the RPC server.

    from uiautomator import device as d

    d.info Traceback (most recent call last): File "", line 1, in File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 412, in info return self.server.jsonrpc.deviceInfo() File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 319, in jsonrpc self.start() File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 337, in start raise IOError("RPC server not started!") IOError: RPC server not started!

    Did i forgot some steps?

    opened by ZhouLihua 9
  • Communicating two devices using uiautomator

    Communicating two devices using uiautomator

    Can we communicate two devices with single script sending one command to call to second device and in the second device can we receive the call, with same one script using this framework.

    I know using python framework for android we can achieve this by connecting one device as master and another device as slave.

    opened by satishsn1 9
  • can't start uiautomator - httplib.InvalidURL: nonnumeric port: 'aport'

    can't start uiautomator - httplib.InvalidURL: nonnumeric port: 'aport'

    Hi, I have following error on 'd.info()'

    echo 'from uiautomator import device as d;print(d.info)' | python
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 476, in info
        return self.server.jsonrpc.deviceInfo()
      File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 369, in wrapper
        server.start()
      File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 385, in start
        files = self.download_and_push()
      File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 342, in download_and_push
        self.download(filename, url)
      File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 350, in download
        res = urllib2.urlopen(url)
      File "/usr/lib/python2.7/urllib2.py", line 127, in urlopen
        return _opener.open(url, data, timeout)
      File "/usr/lib/python2.7/urllib2.py", line 404, in open
        response = self._open(req, data)
      File "/usr/lib/python2.7/urllib2.py", line 422, in _open
        '_open', req)
      File "/usr/lib/python2.7/urllib2.py", line 382, in _call_chain
        result = func(*args)
      File "/usr/lib/python2.7/urllib2.py", line 1222, in https_open
        return self.do_open(httplib.HTTPSConnection, req)
      File "/usr/lib/python2.7/urllib2.py", line 1153, in do_open
        h = http_class(host, timeout=req.timeout) # will parse host:port
      File "/usr/lib/python2.7/httplib.py", line 1164, in __init__
        source_address)
      File "/usr/lib/python2.7/httplib.py", line 704, in __init__
        self._set_hostport(host, port)
      File "/usr/lib/python2.7/httplib.py", line 732, in _set_hostport
        raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
    httplib.InvalidURL: nonnumeric port: 'aport'
    
    

    how can I fix this?

    opened by haradreborn 8
  • Python wrapper for uiautomator is not working

    Python wrapper for uiautomator is not working

    As per your instruction i had installed uiautomator in my ubuntu12.04 machine using below command. pip install uiautomator I had android SDK path in bashrc file also. export ANDROID_HOME=~/adt-bundle-linux-x86_64-20130917/sdk/

    After above steps i had open terminal and opened python and executed below commands python Python 2.7.3 (default, Apr 10 2013, 06:20:15) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information.

    from uiautomator import device as d d.info Traceback (most recent call last): File "", line 1, in File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 381, in info return self.server.jsonrpc.deviceInfo() File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 280, in jsonrpc self.start() File "/usr/local/lib/python2.7/dist-packages/uiautomator.py", line 310, in start raise IOError("RPC server not started!") IOError: RPC server not started! exit()

    I am getting RPC server not found can you please suggest any thing need be configure in my Ubuntu machine to use python wrapper for uiautomator.

    opened by satishsn1 8
  • connect device fail

    connect device fail

    run d.info

    throw exception File "uiautomator.py", line 264, in jsonrpc self.start() File "uiautomator.py", line 281, in start files = self.download_and_push() File "uiautomator.py", line 254, in download_and_push adb.cmd("push", filename, "/data/local/tmp/").wait() File "uiautomator.py", line 194, in cmd cmd_line = ["-s", self.device_serial()] + list(args) File "uiautomator.py", line 205, in device_serial devices = self.devices() File "uiautomator.py", line 219, in devices out = self.raw_cmd("devices").communicate()[0].decode("utf-8") File "uiautomator.py", line 199, in raw_cmd cmd_line = [self.adb()] + list(args) File "uiautomator.py", line 176, in adb if "ANDROID_HOME" in os.environ: RuntimeError: maximum recursion depth exceeded while calling a Python object

    opened by e8143c 7
  • Error while trying to use uiautomator modules

    Error while trying to use uiautomator modules

    ..\conftest.py:9: in test_setup d.demo.close_all() ......\lib\demo.py:412: in close_all self.device.press.recent() ........\venv\lib\site-packages\uiautomator_init_.py:74: in call return self.func(*args, **kwargs) ........\venv\lib\site-packages\uiautomator_init_.py:787: in press return self.server.jsonrpc.pressKey(str(key)) ........\venv\lib\site-packages\uiautomator_init.py:421: in wrapper return method_obj(*args, **kwargs) ........\venv\lib\site-packages\uiautomator_init.py:132: in call "%s: %s" % (jsonresult["error"]["data"]["exceptionTypeName"], jsonresult["error"]["message"]) E TypeError: string indices must be integers

    opened by skempegouda 0
  • sometimes, click() returned False.

    sometimes, click() returned False.

    I don't know why, but sometimes the click operation returns false in the code I wrote. I don't know what am I doing wrong.

    from uiautomator import device as d
    
    
    print(d.click(500,500))
    

    please help me.. This code sometimes works, sometimes it doesn't. I tried typing adb kill-server but it didn't work.

    opened by Andromeda606 0
  • LongClick does not seem to work

    LongClick does not seem to work

    Hi,

    I am using uiautomator to explore an Android app programmatically ( org.liberty.android.fantastischmemo)

    I am trying to perform a long click on a ListView to make a context menu visible, however it seems a click a list view item is performed instead. No context menu shows up and it moves to the next screen (which happens when clicking on a menu item) Here's the code I am using:

    from uiautomator import Device
    import sys
    
    
    # get the target device
    d = Device(sys.argv[1])
    
    # check whether the resourceId exists
    if d(resourceId=sys.argv[2]).exists:
    	d(resourceId=sys.argv[2]).long_click()
    

    After the long click, the app transitions from image to image

    instead of image

    Thank you!

    opened by dah-fari7009 1
  • curl: (7) Failed to connect to localhost port 9008: Connection refused

    curl: (7) Failed to connect to localhost port 9008: Connection refused

    C:\Users\Andrew>adb shell curl -d '{"jsonrpc":"2.0","method":"deviceInfo","id":1}' -v localhost:9008/jsonrpc/0
    adb server is out of date.  killing...
    * daemon started successfully *
    *   Trying 127.0.0.1...
    * TCP_NODELAY set
    * connect to 127.0.0.1 port 9008 failed: Connection refused
    * Failed to connect to localhost port 9008: Connection refused
    * Closing connection 0
    curl: (7) Failed to connect to localhost port 9008: Connection refused
    
    Traceback (most recent call last):
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py", line 670, in urlopen
        httplib_response = self._make_request(
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py", line 426, in _make_request
        six.raise_from(e, None)
      File "<string>", line 3, in raise_from
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py", line 421, in _make_request
        httplib_response = conn.getresponse()
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 1349, in getresponse
        response.begin()
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 316, in begin
        version, status, reason = self._read_status()
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 285, in _read_status
        raise RemoteDisconnected("Remote end closed connection without"
    http.client.RemoteDisconnected: Remote end closed connection without response
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\uiautomator\__init__.py", line 427, in wrapper
        return _method_obj(*args, **kwargs)
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\uiautomator\__init__.py", line 112, in __call__
        res = self.pool.urlopen("POST",
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\poolmanager.py", line 336, in urlopen
        response = conn.urlopen(method, u.request_uri, **kw)
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py", line 726, in urlopen
        retries = retries.increment(
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\util\retry.py", line 410, in increment
        raise six.reraise(type(error), error, _stacktrace)
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\packages\six.py", line 734, in reraise
        raise value.with_traceback(tb)
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py", line 670, in urlopen
        httplib_response = self._make_request(
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py", line 426, in _make_request
        six.raise_from(e, None)
      File "<string>", line 3, in raise_from
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\urllib3\connectionpool.py", line 421, in _make_request
        httplib_response = conn.getresponse()
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 1349, in getresponse
        response.begin()
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 316, in begin
        version, status, reason = self._read_status()
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 285, in _read_status
        raise RemoteDisconnected("Remote end closed connection without"
    urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Remote end closed connection without response'))
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "C:\Users\Andrew\Desktop\Coding\CSGO-Tradeups\Purchase Bot\android_buff_automation.py", line 5, in <module>
        print(d.info())
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\uiautomator\__init__.py", line 594, in info
        return self.server.jsonrpc.deviceInfo()
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\uiautomator\__init__.py", line 431, in wrapper
        server.start(timeout=30)
      File "C:\Users\Andrew\AppData\Local\Programs\Python\Python39\lib\site-packages\uiautomator\__init__.py", line 491, in start
        raise IOError("RPC server not started!")
    OSError: RPC server not started!
    

    RPC server does not start. I have tried the "-t" "-r" fix, and I have tried two different phones.

    opened by Andrew3019 0
Releases(0.2.7)
Owner
xiaocong
xiaocong
Selenium-python but lighter: Helium is the best Python library for web automation.

Selenium-python but lighter: Helium Selenium-python is great for web automation. Helium makes it easier to use. For example: Under the hood, Helium fo

Michael Herrmann 3.2k Dec 31, 2022
Minimal example of getting Django + PyTest running on GitHub Actions

Minimal Django + Pytest + GitHub Actions example This minimal example shows you how you can runs pytest on your Django app on every commit using GitHu

Matt Segal 5 Sep 19, 2022
The Good Old Days. | Testing Out A New Module-

The-Good-Old-Days. The Good Old Days. | Testing Out A New Module- Installation Asciimatics supports Python versions 2 & 3. For the precise list of tes

Syntax. 2 Jun 08, 2022
Generates realistic traffic for load testing tile servers

Generates realistic traffic for load testing tile servers. Useful for: Measuring throughput, latency and concurrency of your tile serving stack. Ident

Brandon Liu 23 Dec 05, 2022
Pyramid debug toolbar

pyramid_debugtoolbar pyramid_debugtoolbar provides a debug toolbar useful while you're developing your Pyramid application. Note that pyramid_debugtoo

Pylons Project 95 Sep 17, 2022
This is a bot that can type without any assistance and have incredible speed.

BulldozerType This is a bot that can type without any assistance and have incredible speed. This bot currently only works on the site https://onlinety

1 Jan 03, 2022
Implement unittest, removing all global variable and returning values

Implement unittest, removing all global variable and returning values

Placide 1 Nov 01, 2021
Let your Python tests travel through time

FreezeGun: Let your Python tests travel through time FreezeGun is a library that allows your Python tests to travel through time by mocking the dateti

Steve Pulec 3.5k Dec 29, 2022
This project is used to send a screenshot by email of your MyUMons schedule using Selenium python lib (headless mode)

MyUMonsSchedule Use MyUMonsSchedule python script to send a screenshot by email (Gmail) of your MyUMons schedule. If you use it on Windows, take care

Pierre-Louis D'Agostino 6 May 12, 2022
Front End Test Automation with Pytest Framework

Front End Test Automation Framework with Pytest Installation and running instructions: 1. To install the framework on your local machine: clone the re

Sergey Kolokolov 2 Jun 17, 2022
Mockoon is the easiest and quickest way to run mock APIs locally. No remote deployment, no account required, open source.

Mockoon Mockoon is the easiest and quickest way to run mock APIs locally. No remote deployment, no account required, open source. It has been built wi

mockoon 4.4k Dec 30, 2022
Public repo for automation scripts

Script_Quickies Public repo for automation scripts Dependencies Chrome webdriver .exe (make sure it matches the version of chrome you are using) Selen

CHR-onicles 1 Nov 04, 2021
RAT-el is an open source penetration test tool that allows you to take control of a windows machine.

To prevent RATel from being detected by antivirus, please do not upload the payload to TOTAL VIRUS. Each month I will test myself if the payload gets detected by antivirus. So you’ll have a photo eve

218 Dec 16, 2022
A library for generating fake data and populating database tables.

Knockoff Factory A library for generating mock data and creating database fixtures that can be used for unit testing. Table of content Installation Ch

Nike Inc. 30 Sep 23, 2022
Show surprise when tests are passing

pytest-pikachu pytest-pikachu prints ascii art of Surprised Pikachu when all tests pass. Installation $ pip install pytest-pikachu Usage Pass the --p

Charlie Hornsby 13 Apr 15, 2022
It's a simple script to generate a mush on code forces, the script will accept the public problem urls only or polygon problems.

Codeforces-Sheet-Generator It's a simple script to generate a mushup on code forces, the script will accept the public problem urls only or polygon pr

Ahmed Hossam 10 Aug 02, 2022
Testing - Instrumenting Sanic framework with Opentelemetry

sanic-otel-splunk Testing - Instrumenting Sanic framework with Opentelemetry Test with python 3.8.10, sanic 20.12.2 Step to instrument pip install -r

Donler 1 Nov 26, 2021
Data-Driven Tests for Python Unittest

DDT (Data-Driven Tests) allows you to multiply one test case by running it with different test data, and make it appear as multiple test cases. Instal

424 Nov 28, 2022
Just for testing video streaming using pytgcalls.

tgvc-video-tests Just for testing video streaming using pytgcalls. Note: The features used in this repository is highly experimental and you might not

wrench 34 Dec 27, 2022
Flexible test automation for Python

Nox - Flexible test automation for Python nox is a command-line tool that automates testing in multiple Python environments, similar to tox. Unlike to

Stargirl Flowers 941 Jan 03, 2023