{"id":13492138,"url":"https://github.com/AirtestProject/Poco","last_synced_at":"2025-03-28T09:33:52.233Z","repository":{"id":41368108,"uuid":"118706014","full_name":"AirtestProject/Poco","owner":"AirtestProject","description":"A cross-engine test automation framework based on UI inspection","archived":false,"fork":false,"pushed_at":"2024-01-08T06:46:58.000Z","size":127560,"stargazers_count":1816,"open_issues_count":350,"forks_count":317,"subscribers_count":68,"default_branch":"master","last_synced_at":"2025-03-27T22:07:41.491Z","etag":null,"topics":["android","automated-testing","automation","game","test-automation","test-framework","unity3d"],"latest_commit_sha":null,"homepage":"http://airtest.netease.com/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AirtestProject.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-01-24T03:24:01.000Z","updated_at":"2025-03-24T02:10:39.000Z","dependencies_parsed_at":"2024-01-07T21:02:08.819Z","dependency_job_id":"9925179a-2280-4d43-9034-842340f788f2","html_url":"https://github.com/AirtestProject/Poco","commit_stats":{"total_commits":254,"total_committers":19,"mean_commits":"13.368421052631579","dds":0.5393700787401574,"last_synced_commit":"727f5e9a6f51cd0a9e14bade1a6e7ea6cba6fb0b"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirtestProject%2FPoco","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirtestProject%2FPoco/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirtestProject%2FPoco/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AirtestProject%2FPoco/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AirtestProject","download_url":"https://codeload.github.com/AirtestProject/Poco/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246004175,"owners_count":20708150,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","automated-testing","automation","game","test-automation","test-framework","unity3d"],"created_at":"2024-07-31T19:01:03.430Z","updated_at":"2025-03-28T09:33:52.204Z","avatar_url":"https://github.com/AirtestProject.png","language":"Python","readme":"\n.. image:: doc/img/logo-no-padding.png\n\nPoco ポコ\n=======\n\n|docs| |chat on slack|\n\n**A cross-engine UI automation framework**. ``Unity3D``/``cocos2dx-*``/``Android native APP``/``iOS native APP``/(Other engines SDK)/...\n\nExample\n-------\n\nFirst you should connect your Android phone, for example, via usb cable and enable the **ADB DEBUG MODE**.\n\n.. image:: doc/img/overview.gif\n\n.. code-block:: python\n\n    # coding=utf-8\n\n    import time\n    from poco.drivers.unity3d import UnityPoco\n\n    poco = UnityPoco()\n\n    poco('btn_start').click()\n    time.sleep(1.5)\n\n    shell = poco('shell').focus('center')\n    for star in poco('star'):\n        star.drag_to(shell)\n    time.sleep(1)\n\n    assert poco('scoreVal').get_text() == \"100\", \"score correct.\"\n    poco('btn_back', type='Button').click()\n\n`More examples`_ here.\n\nTools for writing test scripts\n------------------------------\n\nTo retrieve the UI hierarchy of the game, please use our `AirtestIDE`_ (an IDE for writing test scripts) or\nstandalone `PocoHierarchyViewer`_ (to view the hierarchy and attributes only but lightweight) !\n\n.. image:: doc/img/hunter-inspector.png\n\nInstallation\n------------\n\nIn order to use Poco, you must install Poco python library on your host and also install the `poco-sdk`_ in\nyour game/app.\n\n**Poco** can be installed straightforward with ``pip`` command. It is called ``pocoui``.\n\n.. code-block:: bash\n\n    pip install pocoui\n\n\nSDK Integration\n---------------\n\nFor **poco-sdk** integration please refer to `Integration Guide`_\n\nFeatures\n--------\n\n* supports mainstream game engines, including: Unity3D, cocos2dx-js, cocos2dx-lua, Android/iOS native apps\n* retrieves UI Elements Hierarchy in game's runtime\n* is super fast and impact-free to the game\n* allows straightforward SDK integration to the game (within in 5 minutes)\n* provides powerful APIs that are engine independent\n* supports multi-touch e.g. fling/pinch/... (and more is coming soon)\n* support gps, accelerometer and gyro sensors, rotation (landscape/portrait) and other sensors as input (coming soon)\n* is extensible to other private engines by `implementing poco-sdk`_ .\n* is compatible with Python 2.7 and Python 3.3-3.6.\n\n\nDocumentation\n-------------\n\n`Online docs`_.\n\nUse poco on platforms/engines\n-----------------------------\n\nThis section guide you how to start to use poco to write your test cases on different platforms/engines.\n\n`Poco drivers`_\n\nTutorials and examples\n----------------------\n\nThis section will let your know all basic features of poco.\n\n* `basic usage`_\n* `interact with Buttons and Labels`_\n* `drag and swipe operations`_\n* `advanced selections`_\n* `play with coordinate system and local positioning`_\n* `iteration over elements`_\n* `handling exceptions`_\n* `waiting for events`_\n* `play with unittest framework`_\n* `optimize speed by freezing UI`_\n\n.. _basic usage: http://poco.readthedocs.io/en/latest/source/doc/poco-example/basic.html\n.. _interact with Buttons and Labels: http://poco.readthedocs.io/en/latest/source/doc/poco-example/interact_with_buttons_and_labels.html\n.. _drag and swipe operations: http://poco.readthedocs.io/en/latest/source/doc/poco-example/drag_and_swipe_operations.html\n.. _advanced selections: http://poco.readthedocs.io/en/latest/source/doc/poco-example/advanced_selections.html\n.. _play with coordinate system and local positioning: http://poco.readthedocs.io/en/latest/source/doc/poco-example/play_with_coordinate_system_and_local_positioning.html\n.. _iteration over elements: http://poco.readthedocs.io/en/latest/source/doc/poco-example/iteration_over_elements.html\n.. _handling exceptions: http://poco.readthedocs.io/en/latest/source/doc/poco-example/handling_exceptions.html\n.. _waiting for events: http://poco.readthedocs.io/en/latest/source/doc/poco-example/waiting_events.html\n.. _play with unittest framework: http://poco.readthedocs.io/en/latest/source/doc/poco-example/play_with_unittest_framework.html\n.. _optimize speed by freezing UI: http://poco.readthedocs.io/en/latest/source/doc/poco-example/optimize_speed_by_freezing_UI.html\n\n\nHow to use Poco\n---------------\n\nPoco supports different types of engines by different drivers. For different engines please initialize ``poco`` instance\nby corresponding driver. Remember to connect an Android device to your PC/mac with a running game or launch and keep\nthe game/app active on PC/mac.\n\nFollowing example shows how to initialize poco instance for\n\n* Unity3D.\n\n.. code-block:: python\n\n    from poco.drivers.unity3d import UnityPoco\n\n    poco = UnityPoco()\n    # for unity editor on windows\n    # poco = UnityPoco(('localhost', 5001), unity_editor=True)\n\n    ui = poco('...')\n    ui.click()\n\n* Android native APP\n\n.. code-block:: python\n\n    from poco.drivers.android.uiautomation import AndroidUiautomationPoco\n\n    poco = AndroidUiautomationPoco()\n    poco.device.wake()\n    poco(text='Clock').click()\n\n\n* for other engines, refer to `Poco drivers`_ for more details. If poco drivers does not support your engine, please\n  refer to `Integration Guide`_.\n\n\nWorking with Poco Objects\n-------------------------\n\nBasic Selector\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nUI element objects can be selected by invoking ``poco(...)`` function instance. The function traverses through the\nrender tree structure and selects all the corresponding UI elements matching the query expression.\n\nThe function takes one mandatory argument `node name`, the optional arguments can be substituted too and they refer to\nspecific node properties. For more information, refer to `API Reference selecting UI`_.\n\n\n.. code-block:: python\n\n    # select by node name\n    poco('bg_mission')\n    \n    # select by name and other properties\n    poco('bg_mission', type='Button')\n    poco(textMatches='^据点.*$', type='Button', enable=True)\n\n\n.. image:: doc/img/hunter-poco-select-simple.png\n\n\nRelative Selector\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nWhen there is any ambiguity in the selected objects by node names/node types or object unable to select, the relative\nselector tries to select the element object by hierarchy in following manner\n\n.. code-block:: python\n\n    # select by direct child/offspring\n    poco('main_node').child('list_item').offspring('item')\n\n\n.. image:: doc/img/hunter-poco-select-relative.png\n\nSequence Selector\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nTree indexing and traversing is performed by default from up to down or from left to right. In case that\nthe 'not-yet-traversed' nodes are removed from the screen, the exception is raised. The exception is not raised in case\nwhen the 'already-traversed' nodes are removed and in this case the traversing continues in previous order despite\nthe fact that the nodes in views were rearranged during the travers process.\n\n.. code-block:: python\n\n    items = poco('main_node').child('list_item').offspring('item')\n    print(items[0].child('material_name').get_text())\n    print(items[1].child('material_name').get_text())\n\n.. image:: doc/img/hunter-poco-select-sequence.png\n\nIterate over a collection of objects\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nFollowing code snippet shows how to iterate over the collection of UI objects\n\n.. code-block:: python\n\n    # traverse through every item\n    items = poco('main_node').child('list_item').offspring('item')\n    for item in items:\n        item.child('icn_item')\n\n\n.. image:: doc/img/hunter-poco-iteration.png\n\nGet object properties\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nFollowing examples shows how to obtain various properties of an object\n\n.. code-block:: python\n    \n    mission_btn = poco('bg_mission')\n    print(mission_btn.attr('type'))  # 'Button'\n    print(mission_btn.get_text())  # '据点支援'\n    print(mission_btn.attr('text'))  # '据点支援' equivalent to .get_text()\n    print(mission_btn.exists())  # True/False, exists in the screen or not\n\n\nObject Proxy Related Operation\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nThis section describes object proxy related operations\n\nclick\n'''''\n\nThe anchorPoint of UI element is attached to the click point by default. When the first argument\n(the relative click position) is passed to the function, the coordinates of the top-left corner of the bounding box\nbecome ``[0, 0]`` and the bottom right corner coordinates are ``[1, 1]``. The click range area can be less than 0 or\nlarger than 1. If the click range area lies in the interval (0, 1), it means it is beyond the bounding box.\n\nFollowing example demonstrates how to use ``click`` function\n\n.. code-block:: python\n\n    poco('bg_mission').click()\n    poco('bg_mission').click('center')\n    poco('bg_mission').click([0.5, 0.5])    # equivalent to center\n    poco('bg_mission').focus([0.5, 0.5]).click()  # equivalent to above expression\n\n\n.. image:: doc/img/hunter-poco-click.png\n\nswipe\n'''''\n\nThe anchorPoint of UI element is taken as the origin, the swipe action is performed towards the given direction with\nthe certain distance.\n\nFollowing example shows how to use the ``swipe`` function\n\n.. code-block:: python\n\n    joystick = poco('movetouch_panel').child('point_img')\n    joystick.swipe('up')\n    joystick.swipe([0.2, -0.2])  # swipe sqrt(0.08) unit distance at 45 degree angle up-and-right\n    joystick.swipe([0.2, -0.2], duration=0.5)\n\n\n.. image:: doc/img/hunter-poco-swipe.png\n\ndrag\n''''\n \nDrag from current UI element to the target UI element.\n\nFollowing example shows how to use the ``drag_to`` function\n\n.. code-block:: python\n\n    poco(text='突破芯片').drag_to(poco(text='岩石司康饼'))\n\n\n.. image:: doc/img/hunter-poco-drag.png\n\nfocus (local positioning)\n'''''''''''''''''''''''''\n\nThe anchorPoint is set as the origin when conducting operations related to the node coordinates. If the the local click\narea is need, the focus function can be used. The coordinate system is similar to the screen coordinates - the origin\nis put to the top left corner of the bounding box and with length of unit of 1, i.e the coordinates of the center are\nthen ``[0.5, 0.5]`` and the bottom right corner has coordinates ``[1, 1]``.\n\n\n.. code-block:: python\n\n    poco('bg_mission').focus('center').click()  # click the center\n\n\nThe focus function can also be used as internal positioning within the objects. Following example demonstrates the\nimplementation of `scroll` operation in `ScrollView`.\n\n.. code-block:: python\n\n    scrollView = poco(type='ScollView')\n    scrollView.focus([0.5, 0.8]).drag_to(scrollView.focus([0.5, 0.2]))\n\n\nwait\n''''\n\nWait for the target objects to appear on the screen and return the object proxy itself. If the object exists, return\nimmediately.\n\n.. code-block:: python\n\n    poco('bg_mission').wait(5).click()  # wait 5 seconds at most，click once the object appears\n    poco('bg_mission').wait(5).exists()  # wait 5 seconds at most，return Exists or Not Exists\n\n\nGlobal Operation\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n`Poco` framework also allows to perform the operations without any UI elements selected. These operations are called\n`global` operations.\n\nclick\n'''''\n\n.. code-block:: python\n\n    poco.click([0.5, 0.5])  # click the center of screen\n    poco.long_click([0.5, 0.5], duration=3)\n\n\nswipe\n'''''\n\n.. code-block:: python\n\n    # swipe from A to B\n    point_a = [0.1, 0.1]\n    center = [0.5, 0.5]\n    poco.swipe(point_a, center)\n    \n    # swipe from A by given direction\n    direction = [0.1, 0]\n    poco.swipe(point_a, direction=direction)\n\n\nsnapshot\n''''''''\n\nTake a screenshot of the current screen in base64 encoded string. The image format depends on the sdk implementation.\nTake a look at `ScreenInterface.getScreen`_ to dive into sdk implementation details.\n\n**Note**: ``snapshot``  is not supported in some engine implementation of poco.\n\n.. code-block:: python\n\n    from base64 import b64decode\n    \n    b64img, fmt = poco.snapshot(width=720)\n    open('screen.{}'.format(fmt), 'wb').write(b64decode(b64img))\n\n\nExceptions\n----------\n\nThis sections describes the Poco framework errors and exceptions.\n\nPocoTargetTimeout\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n.. code-block:: python\n\n    from poco.exceptions import PocoTargetTimeout\n    \n    try:\n        poco('guide_panel', type='ImageView').wait_for_appearance()\n    except PocoTargetTimeout:\n        # bugs here as the panel not shown\n        raise\n\n\nPocoNoSuchNodeException\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\n.. code-block:: python\n\n    from poco.exceptions import PocoNoSuchNodeException\n    \n    img = poco('guide_panel', type='ImageView')\n    try:\n        if not img.exists():\n            img.click()\n    except PocoNoSuchNodeException:\n        # If attempt to operate inexistent nodes, an exception will be thrown\n        pass\n\n\nUnit Test\n---------\n\nPoco is an automation test framework. For unit testing, please refer to `PocoUnit`_ section. PocoUnit provides a full \nset of assertion methods and furthermore, it is also compatible with the ``unittest`` in Python standard library.\n\n`Tutorial of PocoUnit`_.\n\nSome Concepts\n-------------\n\nThis section describes some basic concepts of Poco. Basic terminology used in following section\n\n* **Target device**: test devices where the apps or games run on, it usually refers to mobile phone devices\n* **UI proxy**: proxy objects within Poco framework, they represent zero (none), one or multiple in-game UI elements\n* **Node/UI element**: UI element instances or nodes in app/game\n* **query expression**: a serializable internal data structure through which Poco interacts with **target devices** and\n  selects the corresponding UI elements. It is not usually needed to pay much attention to this unless it is required\n  to customize the ``Selector`` class.\n\nFollowing images show the UI hierarchy represented in Poco\n\n.. image:: doc/img/hunter-inspector.png\n.. image:: doc/img/hunter-inspector-text-attribute.png\n.. image:: doc/img/hunter-inspector-hierarchy-relations.png\n\nDefinitions of coordinate system and metric space\n\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n\nNormalized Coordinate System\n''''''''''''''''''''''''''''\n\nIn normalized coordinate system, the origin (0, 0) lies on top left corner of the device display. The height and the\nwidth of the screen are chosen as 1 unit of length, refer to image below for more detailed information.\nIn normalized coordinate system, the same UI elements on the devices with different resolution have always the same\nposition and size. This is especially very handy when writing cross-device test cases.\n\nThe space of normalized coordinate system is uniformly distributed, i.e. the coordinates of the screen center are\n(0.5, 0.5) and the computing method of other scalars and vectors are all same in Euclidean space.\n\n.. image:: doc/img/hunter-poco-coordinate-system.png\n\nLocal Coordinate System (local positioning)\n'''''''''''''''''''''''''''''''''''''''''''\n\nThe aim of introducing local coordinate system is to express the coordinates with reference to a certain UI elements.\nThe origin (0,0) of local coordinate system lies on the top left corner of UI bounding box, x-axis goes horizontally\nrightward direction and y-axis goes vertically downwards. The height and the width of UI element are chosen as 1 unit of\nlength. Coordinates are expressed as signed distances from the origin. Other definitions are same as for normalized\ncoordinate system.\n\nLocal coordinate system is more flexible in order to locate the position within or outside of UI element, e.g\nthe coordinates at (0.5, 0.5) corresponds to the center of the UI element while coordinates larger than 1 or less than 0\ncorrespond to the position out of the UI element.\n\n\nJoin to discuss!\n----------------\n\n|chat on slack|\n\nContributions\n-------------\n\nAny pull requests are welcomed! We will have the code checked carefully. Please make sure the codes are compatible with\npython 2/3 and have the same coding style.\n\n.. _poco-sdk: http://poco.readthedocs.io/en/latest/source/doc/integration.html\n.. _implementing poco-sdk: http://poco.readthedocs.io/en/latest/source/doc/implementation_guide.html\n.. _Integration Guide: http://poco.readthedocs.io/en/latest/source/doc/integration.html\n.. _Integration Guide for NetEase: http://poco.readthedocs.io/en/latest/source/doc/integration.html#netease-internal-engines\n.. _More examples: http://poco.readthedocs.io/en/latest/source/doc/poco-example/index.html\n.. _Hunter内嵌inspector: http://poco.readthedocs.io/en/latest/source/doc/hunter-inspector-guide.html\n.. _网易游戏项目测试脚本标准模板: http://poco.readthedocs.io/en/latest/source/doc/netease-internal-use-template.html\n.. _Tutorial of PocoUnit: http://poco.readthedocs.io/en/latest/source/doc/poco-example/play_with_unittest_framework.html\n.. _Poco drivers: http://poco.readthedocs.io/en/latest/source/doc/poco_drivers.html\n\n.. _AirtestIDE: http://airtest.netease.com/\n.. _Online docs: http://poco.readthedocs.io\n.. _API Reference: http://poco.readthedocs.io#api-reference\n.. _API Reference selecting UI: http://poco.readthedocs.io/en/latest/source/poco.pocofw.html#poco.pocofw.Poco.__call__\n\n.. _ScreenInterface.getScreen: http://poco.readthedocs.io/en/latest/source/poco.sdk.interfaces.screen.html#poco.sdk.interfaces.screen.ScreenInterface.getScreen\n.. _PocoUnit: https://github.com/AirtestProject/PocoUnit\n.. _PocoHierarchyViewer: http://poco.readthedocs.io/en/latest/source/doc/about-standalone-inspector.html\n\n\n.. |docs| image:: https://readthedocs.org/projects/poco/badge/?version=latest\n    :target: http://poco.readthedocs.io/en/latest/?badge=latest\n    :alt: Documentation Status\n\n.. |chat on slack| image:: doc/img/chat_on_slack.png\n    :alt: chat on slack\n    :scale: 100%\n    :target: https://join.slack.com/t/airtestproject/shared_invite/enQtMzYwMjc2NjQzNDkzLTcyMmJlNjgyNjgzZTRkNWRiYmE1YWI1ZWE5ZmQwYmM1YmY3ODZlMDc0YjkwMTQ5NDYxYmEyZWU1ZTFlZjg3ZjI\n","funding_links":[],"categories":["Python","E2E Test"],"sub_categories":["Framework"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAirtestProject%2FPoco","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FAirtestProject%2FPoco","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FAirtestProject%2FPoco/lists"}