Skip to main content

crosslocator

Define a UI selector once. Resolve it on every platform.

Cross-platform test automation means maintaining the same element for Android, iOS, iPadOS, Windows and the web. Most teams end up either duplicating selectors or scattering if platform == ... branches through their page objects.

crosslocator lets you declare a selector once, per platform, and resolves the right one at runtime — from pure Python (Appium), Robot Framework, or any other framework. It only routes selector strings; it never wraps your driver.

from crosslocator import Locator

ADD_PATIENT = Locator(
    android="accessibility_id=add_patient",
    ios="add_patient",
    windows='//Button[@Name="Add"]',
    default="id=add",
)

ADD_PATIENT.for_platform("ios")   # -> "add_patient"

Installation

pip install crosslocator

Zero runtime dependencies.

Why

  • One source of truth per element — no duplicated selectors, no platform if/else.
  • Framework-agnostic — Appium in plain Python, Robot Framework, or anything else.
  • Sensible fallbacks — iPad inherits from iOS, and a shared default covers the rest.
  • Typed and dependency-free.

Quick start (Python)

from crosslocator import Locator, set_current_platform

ADD_PATIENT = Locator(
    android="accessibility_id=add_patient",
    ios="add_patient",
    windows='//Button[@Name="Add"]',
)

set_current_platform("android")   # usually done once, at session start
ADD_PATIENT.resolve()             # -> "accessibility_id=add_patient"

Robot Framework

*** Settings ***
Library     crosslocator.robot.CrossLocator
Variables   locators.py        # ADD_PATIENT defined as a Locator here

*** Test Cases ***
Open Add Patient
    Set Current Platform    android
    ${selector}=    Resolve Locator    ${ADD_PATIENT}
    # -> pass ${selector} to AppiumLibrary / Browser as usual

How the platform is resolved

resolve() determines the current platform in this order:

  1. an explicit set_current_platform(...)
  2. the CROSSLOCATOR_PLATFORM environment variable
  3. a registered provider — typically an Appium session (see below)

Automatic platform detection (Appium)

Let crosslocator read the platform straight from a live Appium session, so you never call set_current_platform by hand.

Python (Appium-Python-Client):

from crosslocator import use_appium

use_appium(driver)      # your Appium webdriver
LOGIN_BUTTON.resolve()  # platform detected from the session capabilities

Robot Framework (AppiumLibrary):

Open Application    ${REMOTE_URL}    platformName=Android    ...
Use Appium Session
${selector}=    Resolve Locator    ${LOGIN_BUTTON}

iPad is detected from the session device name and resolves to iPad selectors (falling back to iOS when none are defined).

Fallback rules

  • ipad → falls back to ios when no iPad-specific selector is set
  • any platform → falls back to default
  • nothing found → LocatorNotFound

Examples

Runnable examples (no device needed) live in the examples/ folder — a login screen resolved across Android, iOS, iPadOS and Windows, plus a Robot Framework suite.

Roadmap

  • v0.1: the core Locator type, platform resolution, Robot Framework keywords.
  • v0.2 (current): automatic platform detection from a live Appium session.
  • Next: Playwright/Browser helpers, and declarative loading of whole screens from YAML/dict.

Issues and contributions are welcome.

License

MIT © 2026 Julien Becheny

Release files for crosslocator 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for crosslocator 0.2.0
File Size Uploaded
crosslocator-0.2.0.tar.gz 8.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for crosslocator 0.2.0
File Interpreter ABI Platform
crosslocator-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 17.4 kB

Release files / crosslocator-0.2.0.tar.gz

Download URL crosslocator-0.2.0.tar.gz
Size 8.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b8fe534088357caf956451af334c394756bcbb595e0adfa3658e1e9fbc83b858
BLAKE2b-256 checksum
How to use checksums
018fed37c5616a136d2cab390a9483e082fc4899e907c702a32d7c868c0b1501
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release files / crosslocator-0.2.0-py3-none-any.whl

Download URL crosslocator-0.2.0-py3-none-any.whl
Size 8.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d222c6a5ddbeabd984002548530b01ab74979779fa8e5d815db255ba0baae0d6
BLAKE2b-256 checksum
How to use checksums
ae6080b40b1351f09072a0f03774874c51f80c972efe5c84b7a9c05f73c04855
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page