Skip to main content

World's most superior macOS GUI testing framework with background testing

Reason this release was yanked:

Deprecated. Use: cargo install axterminator --features cli

Project description

AXTerminator

PyPI version Python macOS License Rust

World's Most Superior macOS GUI Testing Framework

Background testing • ~250µs element access • Self-healing locators • AI vision fallback

Quick StartFeaturesAPIExamplesDocs


🏆 World First: True Background Testing

Test macOS apps without stealing focus. Continue working while tests run in the background.

import axterminator as ax

# Tests run IN THE BACKGROUND - your active window stays focused!
calculator = ax.app(name="Calculator")
calculator.find("5").click()    # No focus stealing
calculator.find("+").click()    # Continue your work
calculator.find("3").click()    # Tests just work
calculator.find("=").click()    # Magic ✨

⚡ Why AXTerminator?

Capability AXTerminator XCUITest Appium Others
Background Testing WORLD FIRST
Element Access ~250µs ~200ms ~500ms-2s 800-8000× slower
Cross-App Testing ✅ Native Limited
Self-Healing 7 strategies Basic 1-2
AI Vision Fallback ✅ VLM

Quick Start

Installation

pip install axterminator

Basic Usage

import axterminator as ax

# 1. Check accessibility permissions
if not ax.is_accessibility_enabled():
    print("Enable in System Settings > Privacy > Accessibility")
    exit(1)

# 2. Connect to app
app = ax.app(name="Calculator")

# 3. Interact (background mode by default!)
app.find("7").click()
app.find("+").click()
app.find("3").click()
app.find("=").click()
# Result: 10

CLI Tool

# Check permissions
axterminator check

# Find elements
axterminator find Calculator "5"

# Click elements
axterminator click Calculator "+"

# Record interactions
axterminator record Calculator

Features

🎭 Background Testing

# User continues working while tests run!
for i in range(100):
    app.find("Refresh").click()  # All in background

🔧 Self-Healing Locators (7 Strategies)

# Element survives UI changes via fallback strategies:
# 1. data_testid  - Developer-set stable IDs
# 2. aria_label   - Accessibility labels
# 3. identifier   - AX identifier
# 4. title        - Element title (fuzzy matching)
# 5. xpath        - Structural path
# 6. position     - Relative position
# 7. visual_vlm   - AI vision fallback

🤖 AI Vision Detection (VLM)

# When all else fails, use AI to find elements
ax.configure_vlm(backend="mlx")      # Local (fast, private)
ax.configure_vlm(backend="anthropic") # Claude Vision
ax.configure_vlm(backend="openai")    # GPT-4V
ax.configure_vlm(backend="gemini")    # Gemini Vision
ax.configure_vlm(backend="ollama")    # Local Ollama

# Natural language element description
app.find("the blue Save button in the toolbar")

🧪 pytest Integration

import pytest

@pytest.mark.ax_requires_app("Calculator")
def test_addition(ax_app, ax_wait):
    app = ax_app("Calculator")
    app.find("7").click()
    app.find("+").click()
    app.find("3").click()
    app.find("=").click()
    ax_wait(0.1)

🎬 Recording Mode

from axterminator import Recorder

recorder = Recorder(app)
recorder.start()
# ... perform actions ...
recorder.stop()

# Generate test code
print(recorder.generate_test())

API Reference

App Connection

# By name
app = ax.app(name="Safari")

# By bundle ID (recommended)
app = ax.app(bundle_id="com.apple.Safari")

# By PID
app = ax.app(pid=12345)

# Launch if not running
app = ax.app(name="Notes", launch=True)

Finding Elements

# By text/title
button = app.find("Save")

# With timeout
button = app.find("Save", timeout_ms=5000)

# By role
text_field = app.find("", role="AXTextField")

# Find all matching
buttons = app.find_all("role:AXButton")

Actions

# Clicks (background by default)
element.click()
element.double_click()
element.right_click()

# Focused mode (for text input)
element.click(mode=ax.FOCUS)
element.type_text("Hello World!")

# Get properties
print(element.title)
print(element.value)
print(element.role)

Synchronization

from axterminator.sync import wait_for_idle, wait_for_element

# Wait for app to settle
wait_for_idle(app, timeout_ms=5000)

# Wait for element to appear
button = wait_for_element(app, "Done", timeout_ms=3000)

Examples

See examples/ for real-world automation:

Script Description
basic_usage.py Calculator automation
system_preferences.py System Settings navigation
finder_automation.py Finder file operations
notes_app.py Notes app automation
textedit_automation.py Document creation
pytest_example.py pytest integration
self_healing_locators.py Locator strategies
vlm_visual_detection.py VLM fallback demo

Browser Extension

Record browser interactions → generate axterminator code:

  1. Load browser-extension/ in Chrome (Developer mode)
  2. Click extension → Start Recording
  3. Interact with web pages
  4. Copy generated Python code

Installation Options

# Basic
pip install axterminator

# With VLM backends
pip install axterminator[vlm]           # Local MLX
pip install axterminator[vlm-anthropic] # Claude Vision
pip install axterminator[vlm-openai]    # GPT-4V
pip install axterminator[vlm-gemini]    # Gemini Vision
pip install axterminator[vlm-ollama]    # Ollama
pip install axterminator[vlm-all]       # All backends

Requirements

  • macOS 12+ (Monterey or later)
  • Python 3.9+
  • Accessibility permissions granted to terminal/IDE

Building from Source

git clone https://github.com/MikkoParkkola/axterminator
cd axterminator

# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Build
pip install maturin
maturin develop

# Test
pytest python/tests/

Performance

Operation Time
Element access ~250µs
Click ~1ms
Type text ~5ms
Find element ~10-50ms

Benchmarked with cargo bench on M1 MacBook Pro

License

MIT OR Apache-2.0

Contributing

Contributions welcome! See docs/ for architecture details.


Built with 🦀 Rust + 🐍 Python

Report BugRequest Feature

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

axterminator-0.3.2-cp39-abi3-macosx_11_0_arm64.whl (396.9 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

axterminator-0.3.2-cp39-abi3-macosx_10_12_x86_64.whl (410.5 kB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file axterminator-0.3.2-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for axterminator-0.3.2-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 19f7f9b948bea718494c5f3db80782c6a3b053fff460f44aaac253c99a30b387
MD5 15bc13e8201a82957e63d7f6f1fe6b57
BLAKE2b-256 1328cada40f6375f12bd9bc63d5bbda5a6e25403c1a9f54d03ec9850bf3710d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for axterminator-0.3.2-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on MikkoParkkola/axterminator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file axterminator-0.3.2-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for axterminator-0.3.2-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 4db9d1f644b56e2d1c50fd3e4a3855c32c9c94d6e4f0cf94e40044120563a605
MD5 8fdd17e7f40dfcbb8f352f37d69cc1a2
BLAKE2b-256 32128c8eec60ee33801a8014c7d4feef8896ba319d78d29e4649a1141492cabf

See more details on using hashes here.

Provenance

The following attestation bundles were made for axterminator-0.3.2-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on MikkoParkkola/axterminator

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page