## Contents 1. [Introduce Aurum](#introduce-aurum) 2. [Command List](#command-list) 3. [Running on TV](#running-on-tv) 4. [Reference and Tip](#reference-and-tip) ## Introduce Aurum - Aurum is a UI automation framework without UI Toolkit dependency. Provides Commands to interact with the device UI by simulation user actions and introspection of the screen content. It relies on the platform accessibility APIs to introspect the screen. - User can use the IDL defined in Proto to create an automation app or script in a variety of languages without a language dependency. ![image](https://media.github.sec.samsung.net/user/39889/files/ff684061-8bee-4a3f-855e-48ac38a5089a) Please refer [grpc](https://grpc.io/) and [proto buffers](https://developers.google.com/protocol-buffers) for more information ## Command List
Name Description Proto definition Python usage
killServer Terminate the org.tizen.aurum-bootstrap process rpc killServer(ReqEmpty) returns (RspEmpty) {} ```python stub.killServer(ReqEmpty()) ```
findElements If an object that satisfies a specific condition is searched on the screen and found, the object list is returned rpc findElements(ReqFindElements) returns (RspFindElements) {}

ReqFindElements :
elementId
automationid
textfield
widgetType
widgetstyle
ischecked
ischeckable
iscliackable
isenabled
isfocused
isfocusable
isscrollable
isselected
isshowing
isactive
mindepth
maxdepth
packagename
textpartialmatch
xpath
geometry
```python #Find Clickable object. def findClickableObject(stub): response = stub.findElements(ReqFindElements(isClickable=True)) for el in response.elements: return True return False #Find Object which has Button as text def findButtonTextObject(stub): response = stub.findElements(ReqFindElements(textField='Button')) for el in response.elements: response = stub.getValue(ReqGetValue(elementId=el.elementId)) return response.stringValue == 'Button' return False #Find entry type object def findEntryObject(stub): response = stub.findElements(ReqFindElements(widgetType='Elm_Entry')) if len(response.elements) <= 0: return False return True #Find object with variouse condition def findTextWithShowingObject(stub): response = stub.findElements(ReqFindElements(textField='Bg', isShowing=True)) if len(response.elements) <= 0: return False return True ```
findElement If an object that satisfies a specific condition is searched on the screen and found, the object is returned rpc findElement(ReqFindElement) returns (RspFindElement) {}

ReqFindElement :
elementId
automationid
textfield
widgetType
widgetstyle
ischecked
ischeckable
iscliackable
isenabled
isfocused
isfocusable
isscrollable
isselected
isshowing
isactive
mindepth
maxdepth
packagename
textpartialmatch
xpath
geometry
```python def findTextWithShowingObject(stub): response = stub.findElements(ReqFindElements(textField='Bg', isShowing=True)) if response.element is None: return False return True ```
getValue Get the value of the object rpc getValue(ReqGetValue) returns (RspGetValue) {}

RspGetValue :
stringValue
intValue
doubleValue
boolValue
```python def findButtonTextObject(stub): response = stub.findElements(ReqFindElements(textField='Button')) for el in response.elements: response = stub.getValue(ReqGetValue(elementId=el.elementId)) return response.stringValue == 'Button' return False ```
setValue Set the value of the object rpc setValue(ReqSetValue) returns (RspSetValue) {}

RspGetValue :
stringValue
intValue
doubleValue
boolValue
```python def setValueTest(stub): response = stub.findElements(ReqFindElements(widgetType='Elm_Entry')) if len(response.elements) <= 0: return False targetObj = response.elements[0].elementId testString = 'set test string by calling SetValue Method' stub.setValue(ReqSetValue(elementId=targetObj, stringValue=testString)) response = stub.getValue(ReqGetValue(elementId=targetObj)) if response.stringValue != testString: return False return True ```
getSize Get geometry of the object rpc getSize(ReqGetSize) returns (RspGetSize) {} ```python def getSizeTest(stub): response = stub.findElements(ReqFindElements(textField='Button')) print("els", response) for el in response.elements: response = stub.getSize(ReqGetSize(elementId=el.elementId)) print(response) return response.size.width + response.size.height > 0 return False ```
clear Clear value of the object rpc clear(ReqClear) returns (RspClear) {} ```python def setValueAndClearTest(stub): response = stub.findElements(ReqFindElements(widgetType='Elm_Entry')) if len(response.elements) <= 0: return False targetObj = response.elements[0].elementId testString = 'set test string by calling SetValue Method' stub.setValue(ReqSetValue(elementId=targetObj, stringValue=testString)) response = stub.getValue(ReqGetValue(elementId=targetObj)) if response.stringValue != testString: return False stub.clear(ReqClear(elementId=targetObj)) response = stub.getValue(ReqGetValue(elementId=targetObj)) if response.stringValue != '': return False return True ```
getAttribute Get attribute of the object rpc getAttribute(ReqGetAttribute) returns (RspGetAttribute) {}

ReqGetAttribute :
VISIBLE
FOCUSABLE
FOCUSED
ENABLED
CLICKABLE
SCROLLABLE
CHECKABLE
CHECKED
SELECTED
SELECTABLE
SHOWING
ACTIVE

RspGetAttribute :
stringValue
intValue
doubleValue
boolValue
```python def getAttributeTest(stub): response = stub.findElements(ReqFindElements(textField='Button')) if len(response.elements) <= 0: return False checkList = [ ['VISIBLE', True], ['FOCUSABLE', True], ['FOCUSED', False], ['ENABLED', True], ['CLICKABLE', True], ['SCROLLABLE', False], ['CHECKABLE', False], ['CHECKED', False], ['SELECTED', False], ['SELECTABLE',True], ['SHOWING', True], ] isFailed = False for el in response.elements: for attr in checkList: if stub.getAttribute(ReqGetAttribute(elementId=el.elementId, attribute=attr[0])).boolValue != attr[1]: isFailed = True if isFailed == True: return False retrurn True ```
click Generate click event rpc click(ReqClick) returns (RspClick) {}

ReqClick :
elementId
coordination
Type :
ELEMENTID
COORD
ATSPI
```python def clickTest(stub): response = stub.findElements(ReqFindElements(textField='Accessibility')) if len(response.elements) <= 0: return False for el in response.elements: stub.click(ReqClick(elementId=el.elementId, type='ELEMENTID')) response = stub.findElements(ReqFindElements(textField='Screen Reader')) if len(response.elements) <= 0: return False for el in response.elements: stub.click(ReqClick(coordination=Point(x=320, y=130), type='COORD')) return True ```
longClick Generate longclick (50ms) event rpc longClick(ReqClick) returns (RspClick) {} ```python def longClickTest(stub): stub.longClick(ReqClick(coordination=Point(x=160, y=160), type='COORD')) return False ```
flick Generate flick event rpc flick(ReqFlick) returns (RspFlick) {} ```python def flickTest(stub): for tryCnt in range(10): print('Flick to bottom to find "Spinner" item @ tries:', tryCnt) stub.flick(ReqFlick(startPoint=Point(x=160, y=359), endPoint=Point(x=160, y=1), durationMs=110)) response = stub.findElements(ReqFindElements(textField='Spinner', isShowing=True) for el in response.elements: return True return False ```
touchDown Generate touchDown event rpc touchDown(ReqTouchDown) returns (RspTouchDown) {} ```python def touchTest(stub): res = stub.touchDown(ReqTouchDown(coordination=Point(x=160,y=640))) print(res) seq = res.seqId if seq < 0: return False for yy in range(640, 30, -10): stub.touchMove(ReqTouchMove(coordination=Point(x=160,y=yy), seqId=seq)) stub.touchUp(ReqTouchUp(coordination=Point(x=160,y=30), seqId=seq)) return True ```
touchMove Generate touchMove event rpc touchMove(ReqTouchMove) returns (RspTouchMove) {} ```python #See touchDown ```
touchUp Generate touchUp event rpc touchUp(ReqTouchUp) returns (RspTouchUp) {} ```python #See touchDown ```
installApp Install application rpc installApp(stream ReqInstallApp) returns (RspInstallApp) {} ```python def installAppTest(stub): response = stub.getAppInfo(ReqGetAppInfo(packageName='org.example.uicomponents')) if (response.isInstalled): return True tpkFile = './org.tizen.uicomponents.arm.tpk' binaryChunk = get_file_chunks(tpkFile) response = stub.installApp(binaryChunk) for waitCnt in range(10): response = stub.getAppInfo(ReqGetAppInfo(packageName='org.example.uicomponents')) print('tries:', waitCnt, 'isInstalled:', response.isInstalled) time.sleep(1) if response.isInstalled: return True return False ```
removeApp Remove application rpc removeApp(ReqRemoveApp) returns (RspRemoveApp) {} ```python def removeAppTest(stub): response = stub.getAppInfo(ReqGetAppInfo(packageName='org.example.uicomponents')) if (response.isInstalled): response = stub.removeApp(ReqRemoveApp(packageName='org.example.uicomponents')) for waitCnt in range(10): response = stub.getAppInfo(ReqGetAppInfo(packageName='org.example.uicomponents')) print('tries:', waitCnt, 'isInstalled:', response.isInstalled) time.sleep(1) if response.isInstalled != True: return True return False ```
getAppInfo Get application info rpc getAppInfo(ReqGetAppInfo) returns (RspGetAppInfo) {}

ReqGetAppInfo :
isRunning
isInstalled
isFocused
```python def getAppInfoTest(stub): return stub.getAppInfo(ReqGetAppInfo(packageName='org.example.uicomponents')).isRunning ```
launchApp Launch application rpc launchApp(ReqLaunchApp) returns (RspLaunchApp) {} ```python def launchAppTest(stub): return stub.getAppInfo(ReqGetAppInfo(packageName='org.example.uicomponents')).isRunning ```
closeApp Close application rpc closeApp(ReqCloseApp) returns (RspCloseApp) {} ```python #Add code ```
getDeviceTime Get device time rpc getDeviceTime(ReqGetDeviceTime) returns (RspGetDeviceTime) {}

ReqGetDeviceTime :
SYSTEM
WALLCLOCK
```python def getDeviceTimeTest(stub): response1 = stub.getDeviceTime(ReqGetDeviceTime(type='SYSTEM')) response2 = stub.getDeviceTime(ReqGetDeviceTime(type='WALLCLOCK')) print(response1, response2) return response2.timestampUTC > response1.timestampUTC; ```
sendKey Generate key event rpc sendKey(ReqKey) returns (RspKey) {}

ReqKey :
BACK
MENU
HOME
VOLUP
VOLDOWN
POWER
XF86
WHEELUP
WHEELDOWN
actionType :
STROKE
LONG_STROKE
PRESS
RELEASE
REPEAT

XF86KeyCode
durationMs
intervalMs
```python def sendKeyTest(stub): response = stub.sendKey(ReqKey(type='WHEELUP', actionType='STROKE')) time.sleep(1) response = stub.sendKey(ReqKey(type='WHEELUP', actionType='STROKE')) time.sleep(1) response = stub.sendKey(ReqKey(type='WHEELDOWN', actionType='STROKE')) time.sleep(1) response = stub.sendKey(ReqKey(type='POWER', actionType='STROKE')) time.sleep(1) response = stub.sendKey(ReqKey(type='POWER', actionType='STROKE')) time.sleep(1) response = stub.sendKey(ReqKey(type='BACK', actionType='STROKE')) time.sleep(1) return True ```
takeScreenshot Take screenshot rpc takeScreenshot(ReqTakeScreenshot) returns (stream RspTakeScreenshot) {} ```python def takeScreenshotTest(stub): responses = stub.takeScreenshot(ReqTakeScreenshot()) image = open("screenshot.png", "wb") for response in responses: image.write(response.image) image.close() return True; ```
dumpObjectTree Get object infomation rpc dumpObjectTree(ReqDumpObjectTree) returns (RspDumpObjectTree) {} ```python def dumpObject(stub): response = stub.findElements(ReqFindElements(textField='Bg', isShowing=True)) if len(response.elements) <= 0: return False for ei in response.elements: response = stub.dumpObjectTree(ReqDumpObjectTree(elementId=ei.elementId)) print(response.roots) ```
setFocus Set focus to specific UI Object rpc setFocus(ReqSetFocus) returns (RspSetFocus) {} ```python def setFocus(stub): response = stub.findElements(ReqFindElements(textField='Button')) if len(response.elements) <= 0: return False stub.setFocus(ReqSetFocus(elementId=response.elements[0).elementId) ```
actionAndWaitEvent Do action and wait event rpc actionAndWaitEvent(ReqActionAndWaitEvent) returns (RspActionAndWaitEvent) {}

ActionType :
CLICK
KEY
EventType
EVENT_WINDOW_ACTIVATE
EVENT_WINDOW_DEACTIVATE
EVENT_STATE_CHANGED_FOCUSED
```python def actionAndWaitEvent(stub): stub.actionAndWaitEvent(ReqActionAndWaitEvent(type=KEY, XF86keyCode='Return', eventType=EVENT_STATE_CHANGE_FOCUSED, timeoutMs=1)) response = stub.findElements(ReqFindElements(textField='Button')) if len(response.elements) <= 0: return False stub.actionAndWaitEvent(ReqActionAndWaitEvent(type=CLICK, elementId=response.elements[0).elementId, eventType=EVENT_WINDOW_ACTIVATE, timeoutMs=5)) ```
### Running on TV - Known issue grpc not support environment that uses proxy on host PC - Pre-condition The TV device and Host PC should be already connected through SDB - Gets Aurum latest version and checkout to tizen branch [Aurum Github](https://github.sec.samsung.net/tizen/aurum) - Set up a python virtual environment and run UI Automation (working directory: aurum/) (host) cd ui_automation/python/tv #### Create virtual env (host) python3 -m venv v #### Activate a virtual env Linux (host) source v/bin/activate Window (host) v/Scripts/activate.bat #### Install required pkg (only once) (python_virtual) pip3 install -r ../../../protocol/resources/python/requirements.txt #### Generate aurum.proto file for python (only once) (python_virtual) python3 -m grpc_tools.protoc --python_out=./ --grpc_python_out=./ -I ./../../../protocol/ ../../../protocol/aurum.proto #### Target setup such as sdb forward, bootstrap execution (python_virtual) python3 ../../../protocol/resources/python/tv/tvSetup.py #### Then add your script then run it (Please refer sample scripts in 'aurum/protocol/resources/python/tv') (python_virtual) python3 sampleWithUtils.py #### Deactivate a virtual env (python_virtual) deactivate ### Reference and Tip - [How to run aurum on TM1](https://code.sec.samsung.net/confluence/display/GFX/04.+NUITizenGallery+Test+Script+Guide) - [NUI automation test](https://github.com/nui-dali/NUIAutomationTest) - [Aurum test sciprts(samples)](https://github.sec.samsung.net/NUI/AurumTestScript) - [Automation application(C++) in target](https://github.sec.samsung.net/TizenUIFW/aurum-test-sample) * Aurum API is not public. we dont recommand direct calling aurum API in target.