Welcome to Poco (ポコ) documentation!¶
A cross-engine UI automation framework. Unity3D
/cocos2dx-*
/Android native APP
/iOS native APP
/(Other engines SDK)/…
Getting Started¶

Poco ポコ¶
A cross-engine UI automation framework. Unity3D
/cocos2dx-*
/Android native APP
/iOS native APP
/(Other engines SDK)/…
Example¶
First you should connect your Android phone, for example, via usb cable and enable the ADB DEBUG MODE.

# coding=utf-8
import time
from poco.drivers.unity3d import UnityPoco
poco = UnityPoco()
poco('btn_start').click()
time.sleep(1.5)
shell = poco('shell').focus('center')
for star in poco('star'):
star.drag_to(shell)
time.sleep(1)
assert poco('scoreVal').get_text() == "100", "score correct."
poco('btn_back', type='Button').click()
More examples here.
Tools for writing test scripts¶
To retrieve the UI hierarchy of the game, please use our AirtestIDE (an IDE for writing test scripts) or standalone PocoHierarchyViewer (to view the hierarchy and attributes only but lightweight) !

Installation¶
In order to use Poco, you must install Poco python library on your host and also install the poco-sdk in your game/app.
Poco can be installed straightforward with pip
command. It is called pocoui
.
pip install pocoui
SDK Integration¶
For poco-sdk integration please refer to Integration Guide
Features¶
- supports mainstream game engines, including: Unity3D, cocos2dx-js, cocos2dx-lua, Android/iOS native apps
- retrieves UI Elements Hierarchy in game’s runtime
- is super fast and impact-free to the game
- allows straightforward SDK integration to the game (within in 5 minutes)
- provides powerful APIs that are engine independent
- supports multi-touch e.g. fling/pinch/… (and more is coming soon)
- support gps, accelerometer and gyro sensors, rotation (landscape/portrait) and other sensors as input (coming soon)
- is extensible to other private engines by implementing poco-sdk .
- is compatible with Python 2.7 and Python 3.3-3.6.
Documentation¶
Use poco on platforms/engines¶
This section guide you how to start to use poco to write your test cases on different platforms/engines.
Tutorials and examples¶
This section will let your know all basic features of poco.
How to use Poco¶
Poco supports different types of engines by different drivers. For different engines please initialize poco
instance
by corresponding driver. Remember to connect an Android device to your PC/mac with a running game or launch and keep
the game/app active on PC/mac.
Following example shows how to initialize poco instance for
- Unity3D.
from poco.drivers.unity3d import UnityPoco
poco = UnityPoco()
# for unity editor on windows
# poco = UnityPoco(('localhost', 5001), unity_editor=True)
ui = poco('...')
ui.click()
- Android native APP
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
poco = AndroidUiautomationPoco()
poco.device.wake()
poco(text='Clock').click()
- for other engines, refer to Poco drivers for more details. If poco drivers does not support your engine, please refer to Integration Guide.
Working with Poco Objects¶
Basic Selector¶
UI element objects can be selected by invoking poco(...)
function instance. The function traverses through the
render tree structure and selects all the corresponding UI elements matching the query expression.
The function takes one mandatory argument node name, the optional arguments can be substituted too and they refer to specific node properties. For more information, refer to API Reference selecting UI.
# select by node name
poco('bg_mission')
# select by name and other properties
poco('bg_mission', type='Button')
poco(textMatches='^据点.*$', type='Button', enable=True)

Relative Selector¶
When there is any ambiguity in the selected objects by node names/node types or object unable to select, the relative selector tries to select the element object by hierarchy in following manner
# select by direct child/offspring
poco('main_node').child('list_item').offspring('item')

Sequence Selector¶
Tree indexing and traversing is performed by default from up to down or from left to right. In case that the ‘not-yet-traversed’ nodes are removed from the screen, the exception is raised. The exception is not raised in case when the ‘already-traversed’ nodes are removed and in this case the traversing continues in previous order despite the fact that the nodes in views were rearranged during the travers process.
items = poco('main_node').child('list_item').offspring('item')
print(items[0].child('material_name').get_text())
print(items[1].child('material_name').get_text())

Iterate over a collection of objects¶
Following code snippet shows how to iterate over the collection of UI objects
# traverse through every item
items = poco('main_node').child('list_item').offspring('item')
for item in items:
item.child('icn_item')

Get object properties¶
Following examples shows how to obtain various properties of an object
mission_btn = poco('bg_mission')
print(mission_btn.attr('type')) # 'Button'
print(mission_btn.get_text()) # '据点支援'
print(mission_btn.attr('text')) # '据点支援' equivalent to .get_text()
print(mission_btn.exists()) # True/False, exists in the screen or not
Global Operation¶
Poco framework also allows to perform the operations without any UI elements selected. These operations are called global operations.
click¶
poco.click([0.5, 0.5]) # click the center of screen
poco.long_click([0.5, 0.5], duration=3)
swipe¶
# swipe from A to B
point_a = [0.1, 0.1]
center = [0.5, 0.5]
poco.swipe(point_a, center)
# swipe from A by given direction
direction = [0.1, 0]
poco.swipe(point_a, direction=direction)
snapshot¶
Take a screenshot of the current screen in base64 encoded string. The image format depends on the sdk implementation. Take a look at ScreenInterface.getScreen to dive into sdk implementation details.
Note: snapshot
is not supported in some engine implementation of poco.
from base64 import b64decode
b64img, fmt = poco.snapshot(width=720)
open('screen.{}'.format(fmt), 'wb').write(b64decode(b64img))
Exceptions¶
This sections describes the Poco framework errors and exceptions.
PocoTargetTimeout¶
from poco.exceptions import PocoTargetTimeout
try:
poco('guide_panel', type='ImageView').wait_for_appearance()
except PocoTargetTimeout:
# bugs here as the panel not shown
raise
PocoNoSuchNodeException¶
from poco.exceptions import PocoNoSuchNodeException
img = poco('guide_panel', type='ImageView')
try:
if not img.exists():
img.click()
except PocoNoSuchNodeException:
# If attempt to operate inexistent nodes, an exception will be thrown
pass
Unit Test¶
Poco is an automation test framework. For unit testing, please refer to PocoUnit section. PocoUnit provides a full
set of assertion methods and furthermore, it is also compatible with the unittest
in Python standard library.
Some Concepts¶
This section describes some basic concepts of Poco. Basic terminology used in following section
- Target device: test devices where the apps or games run on, it usually refers to mobile phone devices
- UI proxy: proxy objects within Poco framework, they represent zero (none), one or multiple in-game UI elements
- Node/UI element: UI element instances or nodes in app/game
- query expression: a serializable internal data structure through which Poco interacts with target devices and
selects the corresponding UI elements. It is not usually needed to pay much attention to this unless it is required
to customize the
Selector
class.
Following images show the UI hierarchy represented in Poco



Definitions of coordinate system and metric space¶
Normalized Coordinate System¶
In normalized coordinate system, the origin (0, 0) lies on top left corner of the device display. The height and the width of the screen are chosen as 1 unit of length, refer to image below for more detailed information. In normalized coordinate system, the same UI elements on the devices with different resolution have always the same position and size. This is especially very handy when writing cross-device test cases.
The space of normalized coordinate system is uniformly distributed, i.e. the coordinates of the screen center are (0.5, 0.5) and the computing method of other scalars and vectors are all same in Euclidean space.

Local Coordinate System (local positioning)¶
The aim of introducing local coordinate system is to express the coordinates with reference to a certain UI elements. The origin (0,0) of local coordinate system lies on the top left corner of UI bounding box, x-axis goes horizontally rightward direction and y-axis goes vertically downwards. The height and the width of UI element are chosen as 1 unit of length. Coordinates are expressed as signed distances from the origin. Other definitions are same as for normalized coordinate system.
Local coordinate system is more flexible in order to locate the position within or outside of UI element, e.g the coordinates at (0.5, 0.5) corresponds to the center of the UI element while coordinates larger than 1 or less than 0 correspond to the position out of the UI element.
Join to discuss!¶
Contributions¶
Any pull requests are welcomed! We will have the code checked carefully. Please make sure the codes are compatible with python 2/3 and have the same coding style.
Install Poco and PocoSDK¶
In order to use Poco, you must install Poco python library on your host and also install the poco-sdk in your game/app.
Poco can be installed straightforward with pip
command
pip install pocoui
For poco-sdk integration please refer to Integration Guide
Using Poco as Python package¶
Simple demo¶
The following example shows a simple script on demo game using Unity3D. Check More examples section for more detailed info.
First you should connect your Android phone, for example, via usb cable and enable the ADB DEBUG MODE.

# coding=utf-8
import time
from poco.drivers.unity3d import UnityPoco
poco = UnityPoco()
poco('btn_start').click()
time.sleep(1.5)
shell = poco('shell').focus('center')
for star in poco('star'):
star.drag_to(shell)
time.sleep(1)
assert poco('scoreVal').get_text() == "100", "score correct."
poco('btn_back', type='Button').click()
Tools for writing test scripts¶
To retrieve the UI hierarchy of the game, please use our AirtestIDE (an IDE for writing test scripts) or standalone PocoHierarchyViewer (to viewer the hierarchy and attributes only but lightweight) !

Use poco on platforms/engines¶
This section guide you how to start to use poco to write your test cases on different platforms/engines.
Tutorials and examples¶
This section will let your know all basic features of poco.
API reference¶
Poco API¶
You can find all functions/methods for writing test scripts under the following links.
poco.pocofw module¶
-
class
Poco
(agent, **options)[source]¶ Bases:
poco.acceleration.PocoAccelerationMixin
Poco standard initializer.
Parameters: - agent (
PocoAgent
) – an agent object for Poco to communicate with the target device. SeePocoAgent
definition for more details. - options –
action_interval
: time interval to wait for the action (such as touch or swipe) completion performed on device and for the UI to become still (stable). Default value is 0.8s.poll_interval
: the minimum time needed between each poll events (such as waiting for UI element to appear on the screen). Polling is done periodically.pre_action_wait_for_appearance
: time interval to wait before the action (such as click or swipe) is performed. If the target UI element does not appear on the screen after this time interval, thePocoNoSuchNodeException
is raisedtouch_down_duration
: Touch down step duration of the click operation last for. If this argument is provided, this value will set toself.agent.input
module. Note that not all implementation of poco support this parameter. If not support, you may see a warning.reevaluate_volatile_attributes
: Re-select target UI proxy when retrieving volatile attributes. Poco drivers that using hrpc connections should default to beFalse
as hrpc always reevaluate the attributes remotely. This option is useful forStdPoco
driver and should be handled byStdPoco
.
-
__call__
(name=None, **kw)[source]¶ Call Poco instance to select the UI element by query expression. Query expression can contain specific name and/or other attributes. Invisible UI elements will be skipped even if “visible=False” argument is set.
Selection process is not executed instantly, the query expression is stored in the UI proxy and the selection is executed only then when the UI element(s) info is required (such get the point coordinates where to click, and/or retrieve the specific attribute value).
Examples
This example shows selecting a Button named ‘close’:
poco = Poco(...) close_btn = poco('close', type='Button')
Parameters: name (
str
) – name of the UI element to be selectedKeyword Arguments: - xx – arbitrary key value pair that stands for selecting the UI matching the value of
UI.xx
- xxMatches (
str
) – arbitrary key value pair that stands for selecting the UI matching the regular expression patternUI.xx
In keyword args, you can only use xx or xxMatches at the same time. Using both with the same attribute does not make sense. Besides, xx should not start with
_
(underscore) as attributes start with_
are private attributes that used by sdk implementation.# select the UI element(s) which text attribute matches the pattern '^close.*$' poco = Poco(...) arb_close_btn = poco(textMatches='^close.*$')
Returns: UI proxy object representing the UI element matches the given query expression. Return type: UIObjectProxy
- xx – arbitrary key value pair that stands for selecting the UI matching the value of
-
add_post_action_callback
(cb)[source]¶ Register a callback function to be invoked after each action (such as touch or swipe).
The arguments to be passed are identical to the callback function in
add_pre_action_callback
.Parameters: cb – the callback function
-
add_pre_action_callback
(cb)[source]¶ Register a callback function to be invoked before each action (such as touch or swipe).
The callback function arguments are defined as follows:
action
(str
): name or tag of the actionproxy
(UIObjectProxy
orNoneType
): related UI proxy which is involved in the action itselfargs
(tuple
): all required arguments of the specific action function
Parameters: cb – the callback function
-
agent
¶ Readonly property to access poco agent instance. See
poco.agent.PocoAgent
for more details.Returns: poco agent instance Return type: poco.agent.PocoAgent
-
apply_motion_tracks
(tracks, accuracy=0.004)[source]¶ Similar to click but press the screen for the given time interval and then release
Parameters: - tracks (
list
) – list ofpoco.utils.track.MotionTrack
object - accuracy (
float
) – motion accuracy for each motion steps in normalized coordinate metrics.
- tracks (
-
click
(pos)[source]¶ Perform click (touch, tap, etc.) action on target device at given coordinates.
The coordinates (x, y) are either a 2-list or 2-tuple. The coordinates values for x and y must be in the interval between 0 ~ 1 to represent the percentage of the screen. For example, the coordinates
[0.5, 0.5]
represent the center of the screen and the coordinates[0, 0]
represent the top left corner.See
CoordinateSystem
for more details about coordinate system.Examples
Click the point of
(100, 100)
of screen which resolution is(1920, 1080)
:poco.click([100.0 / 1920, 100.0 / 1080])
Parameters: pos ( list(float, float)
/tuple(float, float)
) – coordinates (x, y) in range of 0 to 1Raises: InvalidOperationException
– when clicked outside of the screen
-
freeze
()[source]¶ Snapshot current hierarchy and cache it into a new poco instance. This new poco instance is a copy from current poco instance (
self
). The hierarchy of the new poco instance is fixed and immutable. It will be super fast when callingdump
function from frozen poco. See the example below.Examples
poco = Poco(...) frozen_poco = poco.freeze() hierarchy_dict = frozen_poco.agent.hierarchy.dump() # will return the already cached hierarchy data
Returns: new poco instance copy from current poco instance ( self
)Return type: Poco
-
get_screen_size
()[source]¶ Get the real physical resolution of the screen of target device.
Returns: float number indicating the screen physical resolution in pixels Return type: tuple
-
long_click
(pos, duration=2.0)[source]¶ Similar to click but press the screen for the given time interval and then release
Parameters: - pos (
2-list/2-tuple
) – coordinates (x, y) in range from 0 to 1 - duration – duration of press the screen
- pos (
-
pinch
(direction=u'in', percent=0.6, duration=2.0, dead_zone=0.1)[source]¶ Squeezing or expanding 2 fingers on the entire screen.
Parameters: - direction (
str
) – pinching direction, only “in” or “out”. “in” for squeezing, “out” for expanding - percent (
float
) – squeezing range from or expanding range to of the entire screen - duration (
float
) – time interval in which the action is performed - dead_zone (
float
) – pinching inner circle radius. should not be greater thanpercent
- direction (
-
scroll
(direction=u'vertical', percent=0.6, duration=2.0)[source]¶ Scroll from the lower part to the upper part of the entire screen.
Parameters: - direction (
str
) – scrolling direction. “vertical” or “horizontal” - percent (
float
) – scrolling distance percentage of the entire screen height or width according to direction - duration (
float
) – time interval in which the action is performed
- direction (
-
sleep_for_polling_interval
()[source]¶ Sleep for fixed number of seconds after each poll event. There is no need to call this method manually. It’s automatically invoked when required.
-
snapshot
(width=720)[source]¶ Take the screenshot from the target device. The supported output format (png, jpg, etc.) depends on the agent implementation.
Parameters: - width (
int
) – an expected width of the screenshot. The real size depends on the agent implementation - might not be possible to obtain the expected width of the screenshot (and) –
Returns: - screen_shot (
str/bytes
): base64 encoded screenshot data - format (
str
): output format ‘png’, ‘jpg’, etc.
Return type: 2-tuple
- width (
-
start_gesture
(pos)[source]¶ Start a gesture action. This method will return a
PendingGestureAction
object which is able to generate decomposed gesture steps. You can invoke.to
and.hold
any times in a chain. See the following example.Examples
poco = Poco(...) # move from screen center to (0.6w, 0.6h) and hold for 1 second # then return back to center poco.start_gesture([0.5, 0.5]).to([0.6, 0.6]).hold(1).to([0.5, 0.5]).up()
Parameters: pos – starting coordinate of normalized coordinate system Returns: an object for building serialized gesture action. Return type: PendingGestureAction
-
swipe
(p1, p2=None, direction=None, duration=2.0)[source]¶ Perform swipe action on target device from point to point given by start point and end point, or by the direction vector. At least one of the end point or direction must be provided.
The coordinates (x, y) definition for points is the same as for
click
event. The components of the direction vector (x, y) are also expressed in the range of the screen from 0 to 1.See
CoordinateSystem
for more details about coordinate system.Examples
Following example shows how to perform a swipe action from (100, 100) to (100, 200) on screen with resolution 1920x1080:
poco.swipe([100.0 / 1920, 100.0 / 1080], [100.0 / 1920, 200.0 / 1080])
Or given by the specific direction instead of end point:
poco.swipe([100.0 / 1920, 100.0 / 1080], direction=[0, 100.0 / 1080])
Parameters: - p1 (
2-list/2-tuple
) – start point - p2 – end point
- direction – swipe direction
- duration (
float
) – time interval in which the swipe action is performed
Raises: InvalidOperationException
– when the start point of the swipe action lies outside the screen- p1 (
-
use_render_resolution
(use=True, resolution=None)[source]¶ Whether to use render resolution
Parameters: - use – True or false
- resolution – render resolution in portrait mode, offset_x, offset_y, offset_width, offset_height, (0, 10, 1080, 1820)
-
wait_for_all
(objects, timeout=120)[source]¶ Wait until all of given UI proxies show up before timeout. All UI proxies will be polled periodically. See option
poll_interval
inPoco
’s initialization for more details.Parameters: - objects (Iterable<
UIObjectProxy
>) – iterable object of the given UI proxies - timeout (
float
) – timeout in seconds, default is 120s
Raises: PocoTargetTimeout
– when not all of UI proxies appeared before timeout- objects (Iterable<
-
wait_for_any
(objects, timeout=120)[source]¶ Wait until any of given UI proxies show up before timeout and return the first appeared UI proxy. All UI proxies will be polled periodically. See options
poll_interval
inPoco
’s initialization for more details.Parameters: - objects (Iterable<
UIObjectProxy
>) – iterable object of the given UI proxies - timeout (
float
) – timeout in seconds, default is 120s
Returns: the first appeared UI proxy
Return type: Raises: PocoTargetTimeout
– when none of UI proxies appeared before timeout- objects (Iterable<
- agent (
poco.proxy module¶
-
class
UIObjectProxy
(poco, name=None, **attrs)[source]¶ Bases:
object
UI Proxy class that represents the UI element on target device.
Any action performing on this instance is handled by Poco. It is not necessary to initialize this object manually. See
QueryCondition
for more details about how to select the UI elements.Parameters: - poco – the poco instance
- name – query condition of “name” attribute, i.e. the UI element(s) with
name
name will be selected - attrs – other query expressions except for the
name
See also
-
__getitem__
(item)[source]¶ Select the specific UI element by index. If this UI proxy represents a set of UI elements, then use this method to access the specific UI element. The new UI element will be wrapped by UIObjectProxy instance and therefore the returned value is also the UI proxy object.
The order of UI elements are determined by their position on the screen and not by the selection sequence. This rule is called “L2R U2D” (one by one from left to right, line by line from up to down), i.e. the most top left UI element is always the first one. See
IterationOverUI
for more details.Warning
This method may cause some performance issues depending on implementation of PocoAgent.
Parameters: item ( int
) – the index.Returns: a new UI proxy object representing the n-th of the current UI elements. Return type: UIObjectProxy
-
__iter__
()[source]¶ Similar method to
.__getitem__()
with the difference that this method iterates over all UI elements. The order rules of UI elements is same as for.__getitem__()
. SeeIterationOverUI
for more details.Yields: UIObjectProxy
– a generator yielding new UI proxy represents the specific UI element iterated overRaises: PocoTargetRemovedException
– when hierarchy structure has changed and it is attempted to access to the nonexistent UI element over the iteration
-
__len__
()[source]¶ Return the number of selected UI elements.
Returns: returns 0 if none of the UI element matches the query expression otherwise returns the number of selected UI elements Return type: int
-
attr
(*args, **kwargs)[source]¶ Retrieve the attribute of UI element by given attribute name. Return None if attribute does not exist. If attribute type is
str
, it is encoded to utf-8 asstr
in Python2.7.Parameters: name – attribute name, it can be one of the following or any other customized type implemented by SDK
- visible: whether or not it is visible to user
- text: string value of the UI element
- type: the type name of UI element from remote runtime
- pos: the position of the UI element
- size: the percentage size [width, height] in range of 0~1 according to the screen
- name: the name of UI element
- …: other sdk implemented attributes
Returns: None if no such attribute or its value is None/null/nil/etc. Otherwise the attribute value is returned. The returned value type is json serializable. In both py2 and py3, if the attribute value in remote is a text-like object, the return value type will be str
.Raises: PocoNoSuchNodeException
– when the UI element does not existsNote
Exception
NodeHasBeenRemovedException
is caught automatically.
-
child
(name=None, **attrs)[source]¶ Select the direct child(ren) from the UI element(s) given by the query expression, see
QueryCondition
for more details about the selectors.Parameters: - name – query expression of attribute “name”, i.e. the UI elements with
name
name will be selected - attrs – other query expression except for the
name
Returns: a new UI proxy object representing the child(ren) of current UI element(s)
Return type: - name – query expression of attribute “name”, i.e. the UI elements with
-
children
()[source]¶ The same as
.child()
but it selects all children from the UI element(s).Returns: a new UI proxy object Return type: UIObjectProxy
-
click
(*args, **kwargs)[source]¶ Perform the click action on the UI element(s) represented by the UI proxy. If this UI proxy represents a set of UI elements, the first one in the set is clicked and the anchor point of the UI element is used as the default one. It is also possible to click another point offset by providing
focus
argument.See
CoordinateSystem
for more details.Parameters: - focus (2-
tuple
/2-list
/str
) – an offset point (x, y) from the top left corner of the UI element(s), values must be in range of 0~1. This argument can be also specified by ‘anchor’ or ‘center’. ‘Center’ means to click the center of bounding box of UI element. - sleep_interval – number of seconds to wait after this action. Default is None which is the default sleep
interval. This value can be configured by Poco initialization. See configuration at poco
initialization
for more details.
Raises: PocoNoSuchNodeException
– raised when the UI element does not exist- focus (2-
-
double_click
(*args, **kwargs)[source]¶ Perform the double click action on the UI element(s) represented by the UI proxy. If this UI proxy represents a set of UI elements, the first one in the set is clicked and the anchor point of the UI element is used as the default one. It is also possible to click another point offset by providing
focus
argument.See
CoordinateSystem
for more details.Parameters: - focus (2-
tuple
/2-list
/str
) – an offset point (x, y) from the top left corner of the UI element(s), values must be in range of 0~1. This argument can be also specified by ‘anchor’ or ‘center’. ‘Center’ means to double click the center of bounding box of UI element. - sleep_interval – number of seconds to wait after this action. Default is None which is the default sleep
interval. This value can be configured by Poco initialization. See configuration at poco
initialization
for more details.
Raises: PocoNoSuchNodeException
– raised when the UI element does not exist- focus (2-
-
drag_to
(target, duration=2.0)[source]¶ Similar to swipe action, but the end point is provide by a UI proxy or by fixed coordinates.
Parameters: - target (
UIObjectProxy
) – a UI proxy or 2-list/2-tuple coordinates (x, y) in NormalizedCoordinate system - duration (
float
) – time interval in which the action is performed
Raises: PocoNoSuchNodeException
– raised when the UI element does not exist- target (
-
exists
(*args, **kwargs)[source]¶ Test whether the UI element is in the hierarchy. Similar to
.attr('visible')
.Returns: True if exists otherwise False Return type: bool
-
focus
(f)[source]¶ Get a new UI proxy copy with the given focus. Return a new UI proxy object as the UI proxy is immutable.
Parameters: f (2- tuple
/2-list
/str
) – the focus point, it can be specified as 2-list/2-tuple coordinates (x, y) in NormalizedCoordinate system or as ‘center’ or ‘anchor’.Returns: a new UI proxy object (copy) Return type: UIObjectProxy
-
get_bounds
(*args, **kwargs)[source]¶ Get the parameters of bounding box of the UI element.
Returns: 4-list (top, right, bottom, left) coordinates related to the edge of screen in NormalizedCoordinate system Return type: list
<float
>
-
get_name
()[source]¶ Get the UI element name attribute
Returns: UI element name attribute Return type: str
-
get_position
(*args, **kwargs)[source]¶ Get the position of the UI elements.
Parameters: focus – focus point of UI proxy, see .focus()
for more detailsReturns: coordinates (x, y) in NormalizedCoordinate system Return type: 2-list/2-tuple Raises: TypeError
– raised when unsupported focus type is specified
-
get_size
(*args, **kwargs)[source]¶ Get the UI element size in
NormalizedCoordinate
system.Returns: size [width, height] in range of 0 ~ 1. Return type: 2- list
-
get_text
()[source]¶ Get the text attribute of the UI element. Return None if no such attribute. Similar to
.attr('text')
.Returns: None if the UI element does not have the text element, otherwise the utf-8 encoded text value. In both py2 and py3, the return value type will be str
.Return type: str
-
invalidate
()[source]¶ Clear the flag to indicate to re-query or re-select the UI element(s) from hierarchy.
alias is refresh()
Example
>>> a = poco(text="settings") >>> print(a.exists()) >>> a.refresh() >>> print(a.exists())
-
long_click
(*args, **kwargs)[source]¶ Perform the long click action on the UI element(s) represented by the UI proxy. If this UI proxy represents a set of UI elements, the first one in the set is clicked and the anchor point of the UI element is used as the default one. Similar to click but press the screen for the given time interval and then release.
Parameters: duration ( float
) – whole action duration.Returns: the same as poco.pocofw.Poco.long_click()
, depending on poco agent implementation.
-
nodes
¶ Readonly property accessing the UI element(s) in the remote runtime.
-
offspring
(name=None, **attrs)[source]¶ Select the offsprings including the direct child(ren) from the UI element(s) given by the query expression, see
QueryCondition
for more details about selectors.Parameters: - name – query expression of attribute “name”, i.e. the UI elements with
name
name will be selected - attrs – other query expression except for the
name
Returns: a new UI proxy object representing the child(ren) of current UI element(s)
Return type: - name – query expression of attribute “name”, i.e. the UI elements with
-
parent
()[source]¶ Select the direct child(ren) from the UI element(s) given by the query expression, see
QueryCondition
for more details about the selectors.Warning
Experimental method, may not be available for all drivers.
Returns: a new UI proxy object representing the direct parent of the first UI element. Return type: UIObjectProxy
-
pinch
(direction=u'in', percent=0.6, duration=2.0, dead_zone=0.1)[source]¶ Squeezing or expanding 2 fingers on this UI with given motion range and duration.
Parameters: - direction (
str
) – pinching direction, only “in” or “out”. “in” for squeezing, “out” for expanding - percent (
float
) – squeezing range from or expanding range to of the bounds of the UI - duration (
float
) – time interval in which the action is performed - dead_zone (
float
) – pinching inner circle radius. should not be greater thanpercent
Raises: PocoNoSuchNodeException
– raised when the UI element does not exist- direction (
-
rclick
(*args, **kwargs)[source]¶ Perform the right click action on the UI element(s) represented by the UI proxy. If this UI proxy represents a set of UI elements, the first one in the set is clicked and the anchor point of the UI element is used as the default one. It is also possible to click another point offset by providing
focus
argument.See
CoordinateSystem
for more details.Parameters: - focus (2-
tuple
/2-list
/str
) – an offset point (x, y) from the top left corner of the UI element(s), values must be in range of 0~1. This argument can be also specified by ‘anchor’ or ‘center’. ‘Center’ means to click the center of bounding box of UI element. - sleep_interval – number of seconds to wait after this action. Default is None which is the default sleep
interval. This value can be configured by Poco initialization. See configuration at poco
initialization
for more details.
Raises: PocoNoSuchNodeException
– raised when the UI element does not exist- focus (2-
-
refresh
()¶ Clear the flag to indicate to re-query or re-select the UI element(s) from hierarchy.
alias is refresh()
Example
>>> a = poco(text="settings") >>> print(a.exists()) >>> a.refresh() >>> print(a.exists())
-
scroll
(direction=u'vertical', percent=0.6, duration=2.0)[source]¶ Simply touch down from point A and move to point B then release up finally. This action is performed within specific motion range and duration.
Parameters: - direction (
str
) – scrolling direction. “vertical” or “horizontal” - percent (
float
) – scrolling distance percentage of selected UI height or width according to direction - duration (
float
) – time interval in which the action is performed
Raises: PocoNoSuchNodeException
– raised when the UI element does not exist- direction (
-
set_text
(text)[source]¶ Set the text attribute of the UI element. If the UI element does not support mutation, an exception is raised
Parameters: text – the text value to be set Raises: InvalidOperationException
– when unable to mutate text value of the UI element
-
setattr
(*args, **kwargs)[source]¶ Change the attribute value of the UI element. Not all attributes can be casted to text. If changing the immutable attributes or attributes which do not exist, the InvalidOperationException exception is raised.
Parameters: - name – attribute name
- val – new attribute value to cast
Raises: InvalidOperationException
– when it fails to set the attribute on UI element
-
sibling
(name=None, **attrs)[source]¶ Select the sibling(s) from the UI element(s) given by the query expression, see
QueryCondition
for more details about the selectors.Parameters: - name – query expression of attribute “name”, i.e. the UI elements with
name
name will be selected - attrs – other query expression except for the
name
Returns: a new UI proxy object representing the child(ren) of current UI element(s)
Return type: - name – query expression of attribute “name”, i.e. the UI elements with
-
start_gesture
()[source]¶ Start a gesture action. This method will return a
PendingGestureAction
object which is able to generate decomposed gesture steps. You can invoke.to
and.hold
any times in a chain. See the following example.Examples
poco = Poco(...) ui1 = poco('xxx') ui2 = poco('yyy') # touch down on ui1 and hold for 1s # then drag to ui2 and hold for 1s # finally release(touch up) ui1.start_gesture().hold(1).to(ui2).hold(1).up()
Note
always starts touching down at the position of current UI object.
Returns: an object for building serialized gesture action. Return type: PendingGestureAction
-
swipe
(*args, **kwargs)[source]¶ Perform a swipe action given by the direction from this UI element. For notices and limitations see
.click()
.Parameters: - direction (2-
tuple
/2-list
/str
) – coordinates (x, y) in NormalizedCoordinate system, it can be also specified as ‘up’, ‘down’, ‘left’, ‘right’. Swipe ‘up’ is equivalent to [0, -0.1], swipe ‘down’ is equivalent to [0, 0.1], swipe ‘left’ is equivalent to [-0.1, 0] and swipe ‘right’ is equivalent to [0.1, 0] - focus (2-
tuple
/2-list
/str
) – see.click()
for more details - duration (
float
) – time interval in which the action is performed
Raises: PocoNoSuchNodeException
– raised when the UI element does not exist- direction (2-
-
wait
(timeout=3)[source]¶ Block and wait for max given time before the UI element appears.
Parameters: timeout – maximum waiting time in seconds Returns: self Return type: UIObjectProxy
-
wait_for_appearance
(timeout=120)[source]¶ Block and wait until the UI element appears within the given timeout. When timeout, the
PocoTargetTimeout
is raised.Parameters: timeout – maximum waiting time in seconds Raises: PocoTargetTimeout
– when timeout
poco.exceptions module¶
-
exception
InvalidOperationException
(message=None)[source]¶ Bases:
poco.exceptions.PocoException
Raised when the operation performing on target device is foreseen, e.g. instruction to click outside the screen is definitely meaningless, then the
InvalidOperationException
is raised.
-
exception
PocoException
(message=None)[source]¶ Bases:
exceptions.Exception
Base class for errors and exceptions of Poco. It is Python3 compatible.
-
exception
PocoNoSuchNodeException
(objproxy)[source]¶ Bases:
poco.exceptions.PocoException
Raised when the UI element specified by query expression cannot be found.
-
exception
PocoTargetRemovedException
(action, objproxy)[source]¶ Bases:
poco.exceptions.PocoException
Raised when the hierarchy structure changed over the selection or when accessing the UI element that is already recycled.
In most cases, there is no need to handle this exception manually. If this exception occurs, it usually means it is a bug in your code rather than application itself. Check your code first. The most of misuses comes from as follows.
Examples
button1 = poco('button1') time.sleep(10) # waiting for long enough before the UI hierarchy changing button1.click() # PocoTargetRemovedException will raise at this line. Because the 'button1' is not on the screen.
-
exception
PocoTargetTimeout
(action, poco_obj_proxy)[source]¶ Bases:
poco.exceptions.PocoException
Raised when the timeout expired while waiting for some condition to be fulfilled, e.g. waiting for the specific UI element but it has not appeared on the screen.
Engine specific API¶
Poco drivers (engine specific poco implementation)¶
For different engines please initialize poco
instance by corresponding driver. Here are API reference of different
drivers.
- Unity3D
- Android native apps
- OSX apps
- Windows apps
- cocos2dx-lua
- cocos2dx-js
- Egret
- NetEase Internal Engines
For other engines and platforms, please refer to Integration guide for more details
For multiple devices cases, please refer to Multiple devices guide for more details.
Poco SDK API¶
poco.sdk package¶
Subpackages¶
poco.sdk.interfaces package¶
The brief introduction:
This package (poco.sdk.interfaces
) defines the main standards for communication interfaces between poco and
poco-sdk. If poco-sdk is integrated with an app running on another host or in different language, then poco-sdk is
called remote runtime. The implementation of these interfaces can be done either remotely or locally depending on
your own choice. If it is done locally, refer to poco.freezeui
for more information.
Poco needs to communicate with the app runtime under the convention of interfaces described below and these interfaces must be properly implemented. Any object implementing the same interface is replaceable and the communication protocol or transport layer has no limitation. Furthermore, in many cases the communication can be customized that one part of interfaces can use HTTP protocol and other can use TCP.
-
class
CommandInterface
[source]¶ Bases:
object
This is one of the main communication interfaces. This interface defines command-level behaviours providing abilities to control remote runtime by sending self-defined command. The provided command can be various type - from string type to specific structure of a dict.
-
class
HierarchyInterface
[source]¶ Bases:
object
This is one of the main communication interfaces. This interface defines hierarchy-related behaviour assembling from
IDumper
,Attributor
andSelector
. The hierarchy mentioned is the real hierarchy on target app runtime, e.g. a game UI hierarchy in its runtime.-
dump
()[source]¶ Get the UI hierarchy with its origin structure and attributes, then store the structure and attributes into a json serializable dictionary.
Returns: dict representing the hierarchy structure. Structure specification refers to IDumper
.Return type: dict
-
getAttr
(nodes, name)[source]¶ Get attribute of UI element.
Parameters: - nodes – UI element or list of UI elements, if there is a list of UI elements provided, then only the first UI element will be used
- name (
str
) – attribute name
-
select
(query, multiple)[source]¶ Select UI element(s) matching the given query expression and return the list of selected UI element(s)
Parameters: - query (
tuple
) – query expression, for the structure specification refer toSelector
. - multiple (
bool
) – whether or not to select multiple elements, if False, the method terminates immediately once the node is found, otherwise the method travers through all nodes and then terminates
Returns: list of UI elements corresponding to the given query expression
Return type: list
- query (
-
setAttr
(nodes, name, value)[source]¶ Set attribute of UI element.
Parameters: - nodes – UI element or list of UI elements, if there is a list of UI elements provided, then only the first UI element will be used
- name (
str
) – attribute name - value – new value to be set.
Raises: UnableToSetAttributeException
– raised when:- fails to set attributes on given UI element
- the engine does not support mutating attributes
- developer does not allow to change the attribute value by implementation
-
-
class
InputInterface
[source]¶ Bases:
object
This is one of the main communication interfaces. This interface ensures the ability for simulated input on target device. So far, the interface supports only some basic methods definitions. The motion event will be added in future to provide full support for mobile devices.
All coordinates are in NormalizedCoordinate system, see
NormalizedCoordinate
for more details.-
applyMotionEvents
(events)[source]¶ Apply a motion event on the device touch panel
Parameters: events ( list
) – list of events. each event is MotionEvent data (['u/d/m/s', (x, y), contact_id]
)
-
click
(x, y)[source]¶ Perform click action as simulated input on target device. Coordinates arguments are all in range of 0~1.
Parameters: - y (
float
) – y-coordinate - x (
float
) – x-coordinate
- y (
-
getTouchDownDuration
()[source]¶ Get touch down duration for each click operation. Each implementation should provide a default value.
Returns: the touch down duration in seconds Return type: float
-
keyevent
(keycode)[source]¶ Send a key event to target device.
Parameters: keycode ( int
orchar
) – Ascii key code
-
longClick
(x, y, duration)[source]¶ Perform press action as simulated input on target device within given seconds. Coordinates arguments are all in range of 0~1.
Parameters: - x (
float
) – x-coordinate - y (
float
) – y-coordinate - duration (
float
) – time interval to perform the action
- x (
-
setTouchDownDuration
(duration)[source]¶ Set touch down duration for each click operation.
Parameters: duration ( float
) – the duration in seconds
-
swipe
(x1, y1, x2, y2, duration)[source]¶ Perform swipe action as simulated input on target device from point A to B within given time interval to perform the action. Coordinates arguments are all in range of 0~1.
Parameters: - x1 (
float
) – x-coordinate of the start point - y1 (
float
) – y-coordinate of the start point - x2 (
float
) – x-coordinate of the end point - y2 (
float
) – y-coordinate of the end point - duration (
float
) – time interval to perform the swipe action
- x1 (
-
-
class
ScreenInterface
[source]¶ Bases:
object
This is one of the main communication interfaces. This interface ensures the ability for accessing the rendering the results presented on screen of target device. Note that rendering results are very often not used in automated testing directly. Following methods definitions can assist to obtain the information about the app.
poco.sdk.std package¶
Submodules¶
poco.sdk.AbstractDumper module¶
-
class
IDumper
[source]¶ Bases:
object
This interface defines the standard dumper behavior. Dumper class is introduced to get the hierarchy information and convert it into serializable data.
-
dumpHierarchy
(onlyVisibleNode)[source]¶ Return the json serializable dictionary holding the hierarchy data. Refer to sample of returned structure object below.
Structure of the dict:
{ # name can be duplicated from the original name or just left the default one # if it cannot be determined, however providing some meaningful name is preferred 'name': '<a recognizable string>' # All available attributes of this node are in form of key-value pairs 'payload': { 'name': '', 'pos': [0, 0], 'size': [1, 1], ... }, # If there is no child, this part can be omitted 'children': [ {...}, # Same structure as this dict. ], }
Returns: hierarchy data or None Return type: dict
orNoneType
-
getRoot
()[source]¶ Return the root node of the UI Hierarchy. The node information is wrapped by
AbstractNode
. See definition ofAbstractNode
for more details.Returns: instance that holds the hierarchy data Return type: inherit from AbstractNode
-
-
class
AbstractDumper
[source]¶ Bases:
poco.sdk.AbstractDumper.IDumper
This class partially implements
IDumper
using general traversal algorithm. In order to dump the hierarchy from the root node, this dumper first retrieves all available attributes of the root node and also the list all its children and then applies the same procedures as described on each child (i.e. treats each child as a root node) until the node that has no child(ren) is reached.-
dumpHierarchy
(onlyVisibleNode=True)[source]¶ Returns: json serializable dict holding the whole hierarchy data Return type: dict
-
dumpHierarchyImpl
(node, onlyVisibleNode=True)[source]¶ Crawl the hierarchy tree using the simple DFS algorithm. The
dump
procedure is the engine independent as the hierarchy structure is wrapped byAbstractNode
and therefore thedump
procedure can be algorithmized.Following code demonstrates the simplest implementation. Feel free to implement your own algorithms to optimize the performance.
Note
Do not explicitly call this method as this is an internal function, call
dumpHierarchy()
function instead if you want to dump the hierarchy.Parameters: - node (
inherit from AbstractNode
) – root node of the hierarchy to be dumped - onlyVisibleNode (
bool
) – dump only the visible nodes or all nodes, default to True
Returns: json serializable dict holding the whole hierarchy data
Return type: dict
- node (
-
poco.sdk.AbstractNode module¶
-
class
AbstractNode
[source]¶ Bases:
object
AbstractNode is a wrapper class that provides UI hierarchy and node info in game engine.
This class uniformly specifies node-related methods such as retrieving the attributes or accessing the parent nodes or their children.
-
enumerateAttrs
()[source]¶ Enumerate all available attributes and yield the 2-tuple (name, value).
Yields: Iterable< str
,ValueType
>
-
getAttr
(attrName)[source]¶ Return the attributes of the node. The list below shows the most used basic attributes used during while writing test code. The implementation class should return the corresponding value as soon as it retrieves its value. If the value cannot be determined, the default value is obtained from super class invocation and returned. See the example below for more detailed information. More attributes can be added in order to enhance the selection and displaying in
Inspector
.The most used basic attributes are listed as follows:
name
: name of the node, use the unique and meaningful name for each node is recommendedtype
: type of the name of the node, it can be either any string, e.g. “android.widget.Button” or just simple as “Button”visible
: True or False whether the node is rendered on screen. In case the return value is False, all children nodes are ignored in Poco selectorpos
: position of the node in screen, return value should be 2-list coordinates (x, y) representing the percentage of the screen. e.g. if the node lies in the center of the screen, the attribute will be[0.5f, 0.5f]
. If the returned value for position is negative, it means the node lies out of the screensize
: size of the node bounding box, similar topos
, value is also a 2-list of the percentage of the screen size, e.g. the screen size is always[1.0f, 1.0f]
, if the node lies in left half side of the screen, its size will be[0.5f, 1.0f]
, the returned value of size should be always positive valuescale
: scale factor applied to the node itself, leave it[1.0f, 1.0f]
by defaultanchorPoint
: 2-list coordinates (x, y) of the anchor expressed in the percentage related to the bounding box of the node, leave it[0.5f, 0.5f]
by default.zOrders
: rendering order of this node, its value is a dictionary such as{"global": 0, "local": 0}
, global zOrder value is compared with all nodes in the hierarchy, local zOrder value is compared with its parent and siblings. The most top nodes have the largest values.
Examples
The following sample code demonstrates some ideas about the implementation of this method:
def getAttr(self, attrName): # basic attributes if attrName == 'name': return self.node.get_name() or '<no name>' elif attrName == 'pos': return self.node.get_position() # ... # extra engine-specific attributes elif attrName == 'rotation': return self.node.get_rotation() # call the super method by default else: return super().getAttr(attrName)
Parameters: attrName ( str
) – attribute nameReturns: JsonSerializable attribute value or None if no such attribute.
-
getAvailableAttributeNames
()[source]¶ Enumerate all available attribute names of this node. This method in base class returns the basic attribute name by default. It is possible to add other customized or engine-specific attributes. See the example below.
Note
It is recommended to always call the super method and return should contain the part from super method.
Examples
This code demonstrates how to implement this method:
def getAvailableAttributeNames(self): return super().getAvailableAttributeNames() + ( # add other engine-specific attribute names here if need. 'rotation', )
Returns: Iterable< str
>
-
getChildren
()[source]¶ Return an iterator over all children nodes of this node. This method is invoked by
Selector
orDumper
to retrieve the UI hierarchy.Returns: Iterable < AbstractNode
>
-
getParent
()[source]¶ Return the parent node of this node. Return None if there is no parent or parent is not accessible or this is the root node. This method is invoked by
Selector
orDumper
when traversing UI hierarchy.Returns: parent node of this node or None. Return type: AbstractNode or NoneType
-
setAttr
(attrName, val)[source]¶ Apply changes of the attribute value to this node. Not all attributes can be modified. The most common attribute to be modified is the text. It is not recommended to modify attributes such as position, name, their modifications can lead to unexpected and false-positive errors.
Parameters: - attrName (
str
) – attribute name - val – attribute value
Returns: True if success else False or raise.
See also
setAttr
inpoco.sdk.interfaces.hierarchy
- attrName (
-
poco.sdk.Attributor module¶
-
class
Attributor
[source]¶ Bases:
object
This is a helper class to access the node attributes. In some cases it is not possible to explicitly invoke the node member functions thus the following two functions are introduced.
The instance of this class will be used in implementation of
HierarchyInterface
.Note
Do not call these methods explicitly in the test codes.
poco.sdk.DefaultMatcher module¶
-
class
DefaultMatcher
[source]¶ Bases:
poco.sdk.DefaultMatcher.IMatcher
Default matcher implementation for poco hierarchy traversing. Including logical query condition and predicate expression. When traversing through the hierarchy tree, matcher will apply the match method on each node of the tree.
The formal definition of query condition as follows:
expr := (op0, (expr0, expr1, ...)) expr := (op1, (arg1, arg2))
op0
str
is logical operator (‘or’ or ‘and’) which has the same semantics as in python, e.g. ‘or’ means this expression/condition matches if any of the exprN matchesop1
str
is comparator, can be one of as follows:op1 := 'attr=' op1 := 'attr.*=' op1 := ... (other customized)
attr=
corresponds toEqualizationComparator
.attr.*=
corresponds toRegexpComparator
.
The
op1
must be a string. TheMatcher
will help to map toComparator
object.
-
class
EqualizationComparator
[source]¶ Bases:
object
Compare two objects using the native equivalence (==) comparison operator
poco.sdk.Selector module¶
-
class
ISelector
[source]¶ Bases:
object
This interface defines the standard selector behavior. Selector is used for selecting the specific UI element(s) by given query expression (formal definitions are in specific implementation classes).
-
select
(cond, multiple=False)[source]¶ Parameters: - cond (
tuple
) – query expressiom - multiple (
bool
) – whether or not to select the multiple elements. If set to True, the method terminates immediately once the node is found, otherwise it traverses through all nodes and then exists
Returns: list <inherited from
AbstractNode
>Return type: list
- cond (
-
-
class
Selector
(dumper, matcher=None)[source]¶ Bases:
poco.sdk.Selector.ISelector
This class implements the standard Selector interface that uses DFS algorithm to travers through tree-like hierarchy structure. It supports flexible query expressions such as parental relationship, attribute predicate, etc. Any combinations of expressions mentioned above are also allowed as the query conditions.
The query expression can be defined as follows:
expr := (op0, (expr0, expr1)) expr := ('index', (expr, :obj:`int`)) expr := <other query condition> See implementation of Matcher.
op0
can be one of the following (‘>’, ‘/’, ‘-‘), each operator stands for as follows:'>': offsprings, select all offsprings matched expr1 from all roots matched expr0. '/': children, select all children matched expr1 from all roots matched expr0. '-': siblings, select all siblings matched expr1 from all roots matched expr0. '^': parent, select the parent of 1st UI element matched expr0. expr1 is always None.
'index'
: select specific n-th UI element from the previous resultsothers
: passes the expression to matcher
Parameters: - dumper (any implementation of
IDumper
) – dumper for the selector - matcher (any implementation of
IMatcher
) –DefaultMatcher
instance by default.
-
selectImpl
(cond, multiple, root, maxDepth, onlyVisibleNode, includeRoot)[source]¶ Selector internal implementation. TODO: add later.
Note
This doc shows only the outline of the algorithm. Do not call this method in your code as this is an internal method.
Parameters: - cond (
tuple
) – query expression - multiple (
bool
) – whether or not to select multiple nodes. If true, all nodes that matches the given condition will return, otherwise, only the first node matches will. - root (inherited from
AbstractNode
) – start traversing from the given root node - maxDepth (
bool
) – max traversing depth - onlyVisibleNode (
bool
) – If True, skip those node which visibility (the value of visible attribute) is False. - includeRoot (
bool
) – whether not not to include the root node if its child(ren) match(es) the node
Returns: - The same as
Return type: list
<inherited fromAbstractNode
>- cond (
poco.sdk.exceptions module¶
This module provides several exceptions for poco-sdk. These exceptions are raised only in sdk corresponding runtime.
-
exception
NoSuchTargetException
[source]¶ Bases:
exceptions.Exception
Raised when the index is out of range for selecting the UI element by given index.
-
exception
NodeHasBeenRemovedException
(attrName, node)[source]¶ Bases:
exceptions.Exception
Raised when the node (UI element) is refreshed (updated, recycled or destroyed) while retrieving the attributes during traversing the hierarchy.
In some engines implementations, the UI hierarchy is refreshed in a stand-alone thread while poco is performing the traverse process, so the engine error might be triggered when poco is trying to retrieve the attribute of the UI element but the attribute is being updated at the same time. In this situation, poco sdk catches the engine error and raises this exception.
-
exception
UnableToSetAttributeException
(attrName, node)[source]¶ Bases:
exceptions.Exception
Raised when settings the attribute of the given UI element failed. In most cases, the reason why it failed is that the UI element does not support mutation. From the point of view of SDK implementation, this exception can be raised proactively to indicate that the modification of the attribute is not allowed.
-
exception
NoSuchComparatorException
(matchingMethod, matcherName)[source]¶ Bases:
exceptions.Exception
Raised when the matcher does not support the given comparison method.
Poco Examples and Tutorials¶
Here are several example poco test scripts. Each example is written by using Unity3D demo game. It is nothing different from other games.
Download the demo game¶
You can have a try most of the example scripts with the super simple demo game we provided.
Tutorial¶
More demo games for testing¶
The following files are standard apps with according poco-sdk integrated. You can download and install on your device to make sure it works for your environment.
PocoSDK Integration Guide¶
PocoSDK implementations for most popular game engines are already provided in poco-sdk repo. You can easily integrate PocoSDK in your game following the corresponding instruction.
Feel free to open an issue if you get stuck in integration.
Unity3D¶
PocoSDK supports Unity3D version 4 & 5, ngui & ugui, C# only for now. If your game is not supported yet, please refer to implementation guide.
- Clone source code from poco-sdk repo.
- Copy the
Unity3D
folder to your unity project script folder. - If you are using
ngui
, just remove the sub folderUnity3D/ugui
. If you are usingugui
, just remove the sub folderUnity3D/ngui
. - Add
Unity3D/PocoManager.cs
as script component on anyGameObject
, generally on main camera.
Cocos2dx-lua¶
PocoSDK supports cocos2dx-lua version >= 3.1.
- Clone the sdk source code from poco-sdk repo.
- Copy the
cocos2dx-lua/poco
folder to your project script folder. You can rename the folder if you wish. - Initialize poco-sdk by copying following code to your game initialization script.
local poco = require('poco.poco_manager')
poco:init_server(15004) -- default port number is 15004, change to another if you like
Note
Your cocos2dx-lua project should at least enable socket
or socket.core
module, as poco requires this module
to setup a tcp server at runtime.
Note
If your cocos2dx-lua project does not have mime
module, it still works but a little slow.
- Check the adb logcat (for Android) whether successfully integrated. (It is highly recommended to use Android Studio.) If you can see the following “LUA-print”, you poco-sdk is successfully integrated.

After integration, you can start to play with poco. Or if you have any problems, feel free to open an issue here. Title format: [cocos2dx-lua sdk integration] xxx
Cocos2dx-js (beta)¶
PocoSDK supports 3.1 <= Cocos2dx version <= 3.13.1 (theoretically). To make sure compatibility across every javascript engines, the javascript sdk is written in ES5.
cocos2d-x 3.13.1 is tested and passed.
- Clone sdk source code from poco-sdk repo.
- Copy the
cocos2dx-js/Poco
folder to your cocos project javascript folder. - As sdk requires WebSocketServer, we should build WebSocketServer module and js bindings in native code.
The WebSocketServer is part of cocos2dx framework but not include by default thus we build it manually by following
steps. See also WebSocketServer reference. You’d better backup your origin
websockets
folder before copying. The js binding for WebSocketServer requires libwebsockets version == 1.6. There may be some incompatibility issues in cocos2d-x itself if your cocos2d-x engine is not using libwebsockets version == 1.6.
cp -r cocos2dx-js/3rd/websockets <your-cocos-project>/frameworks/cocos2d-x/external/websockets
cp cocos2dx-js/3rd/src/* <your-cocos-project>/frameworks/runtime-src/Classes
- Edit
<your-cocos-project>/frameworks/runtime-src/Classes/AppDelegate.cpp
. Add following 2 lines at proper position respectively.
// include it at top
#include "jsb_websocketserver.h"
// register callbacks of websocketserver
sc->addRegisterCallback(register_jsb_websocketserver);


- Edit
<your-cocos-project>/frameworks/runtime-src/proj.android/jni/Android.mk
. Add following boxed line at proper position in your own makefile. If you are using AndroidStudio project, editproj.android-studio/jni/Android.mk
and ensure the path is correct.

...
$(call import-add-path, $(LOCAL_PATH)/../../../cocos2d-x/external)
LOCAL_SRC_FILES := hellojavascript/main.cpp \
../../Classes/AppDelegate.cpp \
../../Classes/WebSocketServer.cpp \
../../Classes/jsb_websocketserver.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \
$(LOCAL_PATH)/../../../cocos2d-x/external/websockets/include/android
LOCAL_STATIC_LIBRARIES := cocos2d_js_static websockets_static
include $(BUILD_SHARED_LIBRARY)
$(call import-module, websockets/prebuilt/android)
$(call import-module, scripting/js-bindings/proj.android)
...
- Edit your
project.json
. Append sdk filenames tojsList
in the following order.
{
// ...
jsList: [
// ...
"src/lib/Poco/sdk/AbstractDumper.js",
"src/lib/Poco/sdk/AbstractNode.js",
"src/lib/Poco/sdk/Attributor.js",
"src/lib/Poco/sdk/DefaultMatcher.js",
"src/lib/Poco/sdk/IScreen.js",
"src/lib/Poco/sdk/Selector.js",
"src/lib/Poco/Cocos2dxNode.js",
"src/lib/Poco/Cocos2dxDumper.js",
"src/lib/Poco/POCO_SDK_VERSION.js",
"src/lib/Poco/Poco.js"
]
}
- Recompile your cocos project
require('Poco')
in your game’s first initialized script to start PocoSDK, and do not destroy it during game’s lifetime.
var PocoManager = window.PocoManager
var poco = new PocoManager()
// add poco on window object to persist
window.poco = poco
If anything goes wrong, please open an issue here. Title format: [cocos2dx-js sdk integration] xxx
Cocos-Creator¶
PocoSDK supports Cocos Creator 2.2.1 or higher.
Cocos Creator 2.2.1 is tested and passed.
Clone sdk source code from poco-sdk repo.
Copy the
cocos-creator/Poco
folder to your cocos project javascript folder.As sdk requires WebSocketServer, we should enable WebSocketServer module and js bindings in native code.
The WebSocketServer is part of cocos2dx framework but not include by default thus we should include it manually by following steps.
- Go to the engine directory.
- Edit the
ccConfig.h
file. The path is like your/path/to/CocosCreator_2.2.1/resources/cocos2d-x/cocos/base/ccConfig.h - Edit line 62. Change
#define USE_WEBSOCKET_SERVER 0
to#define USE_WEBSOCKET_SERVER 1
Recompile your cocos project
require('Poco')
in your game’s first initialized script to start PocoSDK, and do not destroy it during game’s lifetime.
cc.Class({
extends: cc.Component,
.....
//remember to put code in onLoad function
onLoad: function () {
.....
var poco = require("./Poco") // use your own relative path
window.poco = new poco(); // not destroy
cc.log(window.poco);
},
.....
});
Note
Currently only supports Android and Windows platform, and Poco can only be used after packaging. Not available in preview mode.
Unreal¶
(Coming soon.)
Android Native App¶
Nothing to do about integration. Just start writing tests and be happy. See poco for Android Native App section for more details.
Netease Internal Engines¶
Just config the module preload at Hunter. Please append following script to the end of hunter __init__
instruction. Require safaia version >= 1.2.0. Use print Safaia.__version__
to get current version.
Any questions about hunter feel free to contact lxn3032@corp.netease.com
.
- for NeoX
# core (add only if not present)
Safaia().install(require('safaia.init.core'))
# poco uiautomation
PocoUiautomation = require('support.poco.neox.uiautomation')
Safaia().install(PocoUiautomation)
# inspector extension
screen_handler = require('support.poco.neox.screen')()
InspectorExt = require('support.poco.safaia.inspector')
InspectorExt.screen = screen_handler
InspectorExt.dumper = require('support.poco.neox.Dumper')()
Safaia().install(InspectorExt)
- for Messiah
# core (add only if not present)
Safaia().install(require('safaia.init.core'))
# poco uiautomation
PocoUiautomation = require('support.poco.messiah.uiautomation')
Safaia().install(PocoUiautomation)
# inspector extension
screen_handler = require('support.poco.messiah.screen')()
InspectorExt = require('support.poco.safaia.inspector')
InspectorExt.screen = screen_handler
InspectorExt.dumper = require('support.poco.cocos2dx.Dumper')()
Safaia().install(InspectorExt)
- for cocos2dx-* and others: please contact
lxn3032@corp.netease.com
.
Other Engines¶
See implementation guide. This guide helps you implement and integrate PocoSDK with your game step by step.
Dump UI hierarchy example¶
Poco defines an uniform format to serialize UI hierarchy for different game engines. This section shows how to dump UI hierarchy.
import json
from poco.drivers.unity3d import UnityPoco as Poco
poco = Poco()
ui = poco.agent.hierarchy.dump()
print(json.dumps(ui, indent=4))
The following is the snippet of UI hierarchy. All UI elements are organized in dict representing the tree structure. More detailed info about properties are described in .dumpHierarchy().
...
{
"name": "OctopusArea",
"payload": {
"name": "OctopusArea",
"type": "GameObject",
"visible": true,
"clickable": true,
"zOrders": {
"global": 0,
"local": -10
},
"scale": [
1,
1
],
"anchorPoint": [
0.5,
0.5
],
"pos": [
0.130729169,
0.44907406
],
"size": [
0.0859375,
0.125
]
}
"children": [
{...},
...
],
}
...