From: WoochanLee Date: Fri, 21 Oct 2022 07:40:41 +0000 (+0900) Subject: Update README X-Git-Tag: accepted/tizen/unified/20221103.165802~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0e06e930a569e9ed91da8cf9809c4c51c8c9f6c5;p=platform%2Fcore%2Fuifw%2Faurum.git Update README Change-Id: I87d10708dc9eb7f84dce444faede9e5de6dee8aa --- diff --git a/README.md b/README.md index e98e358..167ef94 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,590 @@ -# AURUM(Tizen UI Automator) +## 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¡¯s UI by simulation user actions and introspection of the screen content. + 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. - [List of Supported Command With Python Example](https://code.sec.samsung.net/confluence/pages/viewpage.action?pageId=212993496) +![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 @@ -45,12 +621,15 @@ #### Target setup such as sdb forward, bootstrap execution (python_virtual) python3 ../../../protocol/resources/python/tv/tvSetup.py - #### Then Run your test script (Please refer sample scripts in 'aurum/protocol/resources/python/tv') - (python_virtual) python3 myTest.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.