ATOMac Usage:
Most of the methods in ATOMac works using two well known Mac terminologies
PID: Process ID of an application which can be obtained using 'ps' command in Terminal[For more details on usage of 'ps' command, please visit the man page of the command - "man ps" in Terminal]
BundleId: Bundle Identifier of an application which can be obtained in the property file of any application. Bundle Id usually resides at "/Applications/<App Name>/Content/info.plist" [Eg: Terminal - 'com.apple.Terminal']
Sample:
Lets start with common actions that we do perform during GUI automation.
1. Open an application
2. Get the title of the window
3. Get the buttons present in the window
4. Fetch the attributes of a button
5. Click the button
6. Close the application
Open an application:
>> import atomac
#Importing ATOMac
>> calc = atomac.getAppRefByBundleId("<Bundle Id>")
#Launching the application using BundleId. This returns the python object refering the bundle id of the application
Get the title of the window:
>> calc_window = calc.windows()[0]
#Returns the first window of the application
>> calc_title_unicode = calc_window.AXTitle
#Returns the title of the first window in unicode format
>> calc_title = str(calc_title_unicode)
#Returns the title in string format
Get the buttons present in the window:
>> buttons = calc_window.buttons()
#Returns the list of buttons present in the window
>> button_name = calc_window.buttons("buttonname")[0]
Fetch the attributes of a button:
>> button_attributes = button_name.getAttributes()
#Returns the list of attributes that are associated to the button
Click the button:
>> button_pos = button_name.AXPosition
#Returns the top left most position of the button. Best practice is to find the center position of the button and click it.
>> button_name(clickMouseButtonLeft(button_pos))
#Left click action of the mouse is performed on the object at the mentioned co-ordinates, where 'button_pos' is the co-ordinates
Close the application:
>> atomac.terminateAppRefByBundleId("<Bundle Id>")
#Terminates the application using the bundle identifier
close application is not (terminalAppRefByBundleId), but terminateAppByBundleId
ReplyDeleteHey Thanks much! Its a typo. Have updated the function.
DeleteThis comment has been removed by the author.
ReplyDeleteThanks, nice brief sample of what working with atomac looks like. :)
ReplyDeleteHey Ashok, I am very new to atomac..,
ReplyDelete1) If i use "sheet = window.sheets()", I am getting output as []..., I am not able to access any textbox or button may i know what is the issue and how to fix this ?
2) As you have told above I have used "buttons = window.buttons()" to find the list of buttons in my app and all i got is zoom,minimize and close button there are many other buttons in my app which is not showing up at all
Thanks in advance
Hi Jithendra,
DeleteApologies for very late reply. Have not been active for sometime.
The Application UI you are trying to automate might not have been hierarchied with detailed object names. You might have to contact the dev engineer to specify the detailed names of the button the object properties.
button_name = calc_window.buttons("buttonname")[0]
ReplyDeleteIndexError: list index out of range
how to fix this?
Hi,
ReplyDeleteThis means that 'atomac' is not able to identify any buttons in the specified window and the statement "button_name = calc_window.buttons("buttonname")[0]" is returning an empty list. Hence the error.
Your blog has given me that thing which I never expect to get from all over the websites. Nice post guys!
ReplyDeleteHi Ashok,
ReplyDeleteI see following error while trying to get the elements. can you help me here?
Error: "AttributeError: 'NoneType' object has no attribute 'windows'"
----
app = atomac.launchAppByBundleId("com.apple.calculator")
time.sleep(2)
app_window = your_app.windows()[0]
May be the issue here is
DeleteInstead of using "app_window = your_app.windows()[0]", please give a try as "app_window = app.windows()[0]" since the application instance is assigned to 'app'
Hi,
ReplyDeleteI am very new to Atomac. I want to automate some actions on a gui window that is already launched (not launched by atomac, like autoit works on windows). Is it possible to do in atomac.
Yes. This should be possible. We can get the application instance using the "PID" of the process
DeleteEg;
import atomac
calc = atomac.getAppRefByPid() #Consider we automate Calculator app
calc.findAll()
Above should return something like below
[, , ]
***[, , ] - [atomac.AXClasses.NativeUIElement AXMenuBar 'menu bar', atomac.AXClasses.NativeUIElement AXFunctionRowTopLevelElement 'top level function ...', atomac.AXClasses.NativeUIElement AXFunctionRowTopLevelElement 'top level function ...']
DeleteHow do we get buttons present on form which is launched from other form.
ReplyDeleteFor example Application launches one form, when we click on button on this form it will launch another form where I want to access textbox and buttons of new form....how to do this
Command atomac.terminateAppRefByBundleId("") doesn't work for me
ReplyDeleteSo I've found another command atomac.terminateAppByBundleId("")
and all other command:
>>> dir(atomac)
['AXCallbacks', 'AXClasses', 'AXKeyCodeConstants', 'AXKeyboard', 'Clipboard', 'Error', 'ErrorAPIDisabled', 'ErrorCannotComplete', 'ErrorInvalidUIElement', 'ErrorNotImplemented', 'ErrorUnsupported', 'NativeUIElement', 'Prefs', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_a11y', 'getAppRefByBundleId', 'getAppRefByLocalizedName', 'getAppRefByPid', 'getFrontmostApp', 'launchAppByBundleId', 'launchAppByBundlePath', 'setSystemWideTimeout', 'standard_library', 'terminateAppByBundleId', 'version']