Giter VIP home page Giter VIP logo

pyatomac's Introduction

ATOMac - Automated Testing on Mac

Introduction

We are pleased to introduce the first Python library to fully enable GUI testing of Mac applications via the Apple Accessibility API. This library was created out of desperation. Existing tools such as using appscript to send messages to accessibility objects are painful to write and slow to use. ATOMac has direct access to the API. It's fast and easy to use to write tests.

Getting started

ATOMac requires a system running OS X and Xcode installed. It has been tested extensively on 10.6, 10.7, and 10.8. 10.5 may work. If you experience issues with ATOMac on a particular version of OS X, please open a ticket in the issue tracker.

Systemwide accessibility must be enabled. Check the checkbox: System Preferences > Universal Access > Enable access for assistive devices. Failure to enable this will result in ErrorAPIDisabled exceptions during some module usage.

Installation should be as simple as running the following command line, which will download, build and install ATOMac:

$ sudo pip install pyatomac

Usage

Once the atomac module is installed, you should be able to use it to launch an application:

>>> import atomac
>>> atomac.launchAppByBundleId('com.apple.Automator')

This should launch Automator. Next, get a reference to the UI Element for the application itself:

>>> automator = atomac.getAppRefByBundleId('com.apple.Automator')
>>> automator
<pyatom.AXClasses.NativeUIElement AXApplication u'Automator'>

Now, we can find objects in the accessibility hierarchy:

>>> window = automator.windows()[0]
>>> window.AXTitle
u'Untitled'
>>> sheet = window.sheets()[0]

Note that we retrieved an accessibility attribute from the Window object - AXTitle. ATOMac supports reading and writing of most attributes. Using Xcode's included accessibility inspector can provide a quick way to find these attributes.

There is a shortcut for getting the sheet object which bypasses accessing it through the Window object - ATOMac can search all objects in the hierarchy:

>>> sheet = automator.sheetsR()[0]

There are search methods for most types of accessibility objects. Each search method, such as windows, has a corresponding recursive search function, such as windowsR. The recursive search finds items that aren't just direct children, but children of children. These search methods can be given terms to identify specific elements. Note that * and ? can be used as wildcard match characters in all ATOMac search methods:

>>> close = sheet.buttons('Close')[0]

ATOMac has a method to search for UI Elements that match any number of criteria. The criteria are accessibility attributes:

>>> close = sheet.findFirst(AXRole='AXButton', AXTitle='Close')

FindFirst and FindFirstR return the first item found to match the criteria or None. FindAll and FindAllR return a list of all items that match the criteria or an empty list.

Objects are fairly versatile. You can get a list of supported attributes and actions on an object:

>>> close.getAttributes()
[u'AXRole', u'AXRoleDescription', u'AXHelp', u'AXEnabled', u'AXFocused',
u'AXParent', u'AXWindow', u'AXTopLevelUIElement', u'AXPosition', u'AXSize',
u'AXTitle']
>>> close.AXTitle
u'Close'
>>> close.getActions()
[u'Press']

Performing an action is as natural as:

>>> close.Press()

Any action can be triggered this way.

LDTP

Starting with version 1.0.0, ATOMac now includes compatibility with LDTP, a cross platform automation library. This allows testers to write a single script that will automate test cases on Linux, Windows, and now Mac OS X. Information and documentation on LDTP can be found at the LDTP home page.

LDTP operation is virtually identical to the operation on Linux. The import mechanism is slightly different, since it is shipped with ATOMac. Cross platform scripts executing on the System Under Test should import the LDTP client as follows:

try:
    import ldtp
except ImportError:
    import atomac.ldtp as ldtp

In the future, the LDTP client may be broken out into a separate platform independent module to ameliorate this issue.

Like the Linux platform, the LDTP daemon may be run on the SUT, enabling client/server testing by executing 'ldtp' at a shell prompt. See the LDTP documentation for more details on client/server operation.

Todo and contributing

Although ATOMac is fully functional and drives hundreds of automated test cases at VMware, we have a to-do list to make the project even better.

  • Formatting - this code is not currently PEP-8 compliant.
  • Better mouse handling - for example, a method to smoothly drag from one UI Element to another.
  • Cleanup the search methods - We could use currying to define all the search methods in AXClasses in a cleaner way.

Feel free to submit pull requests against the project on Github. If you're interested in developing ATOMac itself, sign up to the pyatom-dev mailing list.

See also

License

ATOMac is released under the GNU General Public License. See COPYING.txt for more details.

Authors

James Tatum <[email protected]>, Andrew Wu, Jesse Mendonca, Ken Song, Nagappan Alagappan, Yingjun Li, Alexey Kostyrin

And other contributors listed in the CHANGELOG file. Thank you so much!

pyatomac's People

Stargazers

ikun avatar lincoln avatar Huy Z avatar  avatar Roman avatar David McElligott avatar  avatar Stefan S. avatar  avatar  avatar Junho Yeo avatar  avatar Andrew Terekhov avatar LP_Cong avatar

Watchers

James Cloos avatar Aleksei Kostyrin avatar

pyatomac's Issues

_getRunningApps(cls) function conflicts with PyQt

Thank you very much for your contribution to UI automation.
Recently I encountered a problem, when I call _getRunningApps() function, it will kill the Qt event loop, causing the program to exit abnormally.

I think the main reason is because the following code is executed.

def runLoopAndExit():
AppHelper.stopEventLoop()
AppHelper.callLater(1, runLoopAndExit)
AppHelper.runConsoleEventLoop()

and then it kill the Qt Event Loop.

Your repository can run perfectly under MacOS 10.13. I hope you can fix this bug. I think it would be nice to delete these words directly.

Documentation refactoring and improvements

Project documentation needs to be refactored due to last changes in project:

  • Project name and name on pypi is pyatomac
  • Project version: 2.0.x
  • Ported to python 3.6
  • Can be installed with pip and wheels

Also it should be improved with adding more user case examples and documenting more functions

Error installing on 10.13.6. Conversion.h not found

I'm trying to install pyatomac on 10.13.6, but I'm getting the error below. Despite this, I could install manually with: python3 setup.py installl

Installing collected packages: pyatomac
Running setup.py install for pyatomac ... error
Complete output from command /Library/Frameworks/Python.framework/Versions/3.7/bin/python3 -u -c "import setuptools, tokenize;file='/private/var/folders/_l/rgb0q19d6sv693l8nlw3dl0n_g1xc2/T/pip-install-9udpailm/pyatomac/setup.py';f=getattr(tokenize, 'open', open)(file);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, file, 'exec'))" install --record /private/var/folders/_l/rgb0q19d6sv693l8nlw3dl0n_g1xc2/T/pip-record-2ygliobp/install-record.txt --single-version-externally-managed --compile:
running install
running build
running build_py
creating build
creating build/lib.macosx-10.9-x86_64-3.7
creating build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/AXClasses.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/AXKeyCodeConstants.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/version.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/AXCallbacks.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/init.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/Prefs.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/AXKeyboard.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/Clipboard.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
copying atomac/AppHelper.py -> build/lib.macosx-10.9-x86_64-3.7/atomac
creating build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/keypress_actions.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/generic.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/constants.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/combo_box.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/init.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/core.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/test.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/server_exception.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/menu.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/utils.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/text.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/page_tab_list.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/mouse.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/table.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
copying atomac/ldtpd/value.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtpd
creating build/lib.macosx-10.9-x86_64-3.7/atomac/ldtp
copying atomac/ldtp/log.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtp
copying atomac/ldtp/client.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtp
copying atomac/ldtp/init.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtp
copying atomac/ldtp/client_exception.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtp
copying atomac/ldtp/state.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ldtp
creating build/lib.macosx-10.9-x86_64-3.7/atomac/ooldtp
copying atomac/ooldtp/log.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ooldtp
copying atomac/ooldtp/init.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ooldtp
copying atomac/ooldtp/client_exception.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ooldtp
copying atomac/ooldtp/state.py -> build/lib.macosx-10.9-x86_64-3.7/atomac/ooldtp
running build_ext
building 'atomac._a11y' extension
creating build/temp.macosx-10.9-x86_64-3.7
creating build/temp.macosx-10.9-x86_64-3.7/atomac
creating build/temp.macosx-10.9-x86_64-3.7/atomac/_a11y
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -arch x86_64 -g -I/Library/Frameworks/Python.framework/Versions/3.7/include/python3.7m -c atomac/_a11y/a11ymodule.m -o build/temp.macosx-10.9-x86_64-3.7/atomac/_a11y/a11ymodule.o
atomac/_a11y/a11ymodule.m:31:10: fatal error: 'conversion.h' file not found
#include "conversion.h"
^~~~~~~~~~~~~~
1 error generated.
error: command 'gcc' failed with exit status 1

----------------------------------------

Command "/Library/Frameworks/Python.framework/Versions/3.7/bin/python3 -u -c "import setuptools, tokenize;file='/private/var/folders/_l/rgb0q19d6sv693l8nlw3dl0n_g1xc2/T/pip-install-9udpailm/pyatomac/setup.py';f=getattr(tokenize, 'open', open)(file);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, file, 'exec'))" install --record /private/var/folders/_l/rgb0q19d6sv693l8nlw3dl0n_g1xc2/T/pip-record-2ygliobp/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/_l/rgb0q19d6sv693l8nlw3dl0n_g1xc2/T/pip-install-9udpailm/pyatomac/

Thanks for your contribution

Crash(Segmentation fault: 11) when using waitForWindowToAppear

Hi ,
Python app crashes when executing a script that is using waitForWindowToAppear
scripts exits with Segmenation fault:11 when desired window appears while it is waiting for.

code used:

msm = atomac.getAppRefByBundleId(MSM_BUNDLE_ID)
print"waiting for prompt window"
msm.waitForWindowToAppear("WindowTitle", 100)
print "got the prompt window"

the crash report:

Process: Python [73585]
Path: /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
Identifier: Python
Version: 2.7.10 (2.7.10)
Code Type: X86-64 (Native)
Parent Process: bash [71374]
Responsible: Python [73585]
User ID: 501

PlugIn Path: /Users/USER/*/_a11y.so
PlugIn Identifier: _a11y.so
PlugIn Version: ??? (0)

Date/Time: 2018-06-06 17:40:21.514 +0530
OS Version: Mac OS X 10.13.4 (17E199)
Report Version: 12
Bridge OS Version: 3.0 (14Y664)

Time Awake Since Boot: 360000 seconds
Time Since Wake: 3700 seconds

System Integrity Protection: enabled

Crashed Thread: 0 Dispatch queue: com.apple.main-thread

Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000098
Exception Note: EXC_CORPSE_NOTIFY

Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [0]

VM Regions Near 0x98:
-->
__TEXT 000000010cbf5000-000000010cbf7000 [ 8K] r-x/rwx SM=COW /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0 org.python.python 0x00007fff345770c3 0x7fff34523000 + 344259
1 org.python.python 0x00007fff3456ccc2 0x7fff34523000 + 302274
2 _a11y.so 0x000000010d1f54b0 observerCallback + 469
3 com.apple.HIServices 0x00007fff286496ab _XXMIGPostNotification + 790
4 com.apple.HIServices 0x00007fff28657329 _XPostNotification + 351
5 com.apple.HIServices 0x00007fff2862d6f1 mshMIGPerform + 212
6 com.apple.CoreFoundation 0x00007fff29dd3449 CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION + 41
7 com.apple.CoreFoundation 0x00007fff29dd3395 __CFRunLoopDoSource1 + 533
8 com.apple.CoreFoundation 0x00007fff29dcaf50 __CFRunLoopRun + 2848
9 com.apple.CoreFoundation 0x00007fff29dca1a3 CFRunLoopRunSpecific + 483
10 _a11y.so 0x000000010d1f5e80 AXUIElement_setNotification + 873
11 org.python.python 0x00007fff345a3f89 PyEval_EvalFrameEx + 2917
12 org.python.python 0x00007fff345a3232 PyEval_EvalCodeEx + 1551
13 org.python.python 0x00007fff3454a935 0x7fff34523000 + 162101
14 org.python.python 0x00007fff3452d581 PyObject_Call + 97
15 org.python.python 0x00007fff345a6f2a PyEval_EvalFrameEx + 15110
16 org.python.python 0x00007fff345a3232 PyEval_EvalCodeEx + 1551
17 org.python.python 0x00007fff345a92b4 0x7fff34523000 + 549556
18 org.python.python 0x00007fff345a3b45 PyEval_EvalFrameEx + 1825
19 org.python.python 0x00007fff345a3232 PyEval_EvalCodeEx + 1551
20 org.python.python 0x00007fff345a92b4 0x7fff34523000 + 549556
21 org.python.python 0x00007fff345a3b45 PyEval_EvalFrameEx + 1825
22 org.python.python 0x00007fff345a3232 PyEval_EvalCodeEx + 1551
23 org.python.python 0x00007fff345a2c1d PyEval_EvalCode + 32
24 org.python.python 0x00007fff345c1ad1 0x7fff34523000 + 649937
25 org.python.python 0x00007fff345c1b78 PyRun_FileExFlags + 130
26 org.python.python 0x00007fff345c16fa PyRun_SimpleFileExFlags + 706
27 org.python.python 0x00007fff345d296c Py_Main + 3064
28 libdyld.dylib 0x00007fff520d0015 start + 1

Thread 1:
0 libsystem_pthread.dylib 0x00007fff523e7bdc start_wqthread + 0
1 ??? 0x00007000027dfb30 0 + 123145344121648

Thread 0 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000000 rbx: 0x00007fff852f2488 rcx: 0x0000000000000001 rdx: 0x0079e0000079e000
rdi: 0x000000010ec4cf58 rsi: 0x0000000100000000 rbp: 0x00007ffee3007fa0 rsp: 0x00007ffee3007f60
r8: 0x0000000000000000 r9: 0xffffffff00000000 r10: 0x0000000000000000 r11: 0x00007fa55a437508
r12: 0x00007fff852f24c8 r13: 0x0000000000000000 r14: 0x000000010ec4cf58 r15: 0x00007fa55a491270
rip: 0x00007fff345770c3 rfl: 0x0000000000010297 cr2: 0x0000000000000098

Logical CPU: 0
Error Code: 0x00000004
Trap Number: 14

Installation failing on 10.12.6

Hi
I tried to instal atomac using sudo easy_Install atomac on Mac OS 10.12.6

it fails with the following errors:
Reading https://pypi.python.org/simple/atomac/
Download error on https://pypi.python.org/simple/atomac/: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590) -- Some packages may not be found!
Couldn't find index page for 'atomac' (maybe misspelled?)
Scanning index of all packages (this may take a while)
Reading https://pypi.python.org/simple/
Download error on https://pypi.python.org/simple/: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:590) -- Some packages may not be found!
No local packages or download links found for atomac
error: Could not find suitable distribution for Requirement.parse('atomac')

Please suggest what is the work around to install on Mac OS 10.12

It installs without any issue on 10.13

Thanks,
Swetha

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.