Documentation menu

Tutorials

Object Repository

The Object Repository keeps UI selectors in YAML files instead of test code. Tests refer to elements by alias; when the application's UI changes, you edit one YAML entry instead of hunting selectors across fifty test files.

Use it when selectors are shared by many tests, maintained by people who don't write Python, or generated by tooling. For selectors that belong to one screen and one team, Page Objects may read better — the two patterns also combine (a Page Object can resolve its locators from aliases).

1. Define aliases in YAML

Create an objects/ directory next to your tests:

objects/login.yaml
login_window:
  selector:
    title: "Login - MyApp"
  children:
    email_input:
      selector:
        automation_id: txtEmail
        role: Edit
      fallback:
        - name: Email
        - name: "E-mail address"
    password_input:
      selector:
        automation_id: txtPassword
    submit_button:
      selector:
        automation_id: btnLogin
        name: Login

Each alias has a required selector mapping and optional fallback and children. Selector keys accept YAML-friendly names — automation_id, role, name — which map to the underlying criteria (auto_id, control_type, title); the native names work too. A typo in a key (automationid:) fails at load time with the file and path in the message, not deep inside a test.

fallback is a list of alternative selectors tried in order when the primary one stops matching — the same self-healing mechanism as fallback selectors, just declared in data.

2. Load the repository

from dolphin_desktop import objects

objects.discover("objects")          # every *.yaml in the directory
# or explicitly:
objects.load("objects/login.yaml")

print(objects.available())           # ['login_window', ...]

Call it once per session — conftest.py is the natural home:

conftest.py
from dolphin_desktop import objects


def pytest_configure(config):
    objects.discover("objects")

3. Use aliases in tests

Application.window() takes an alias as its first positional argument, and the returned window resolves element() lookups against that alias's children:

def test_login(launch):
    app = launch("myapp.exe")

    win = app.window("login_window")             # alias → title criteria
    win.element("email_input").type_text("user@example.com")
    win.element("password_input").type_text("secret")
    win.element("submit_button").click()

An unknown alias raises AliasNotFoundError naming the alias and the files that were searched.

4. Override hierarchy

Repositories load at one of three levels — workspace < project < test. A higher level wins for the same alias, so a test suite can override one selector from shared defaults without forking the file:

objects.load("shared/objects.yaml",  level="workspace")
objects.load("objects/app.yaml",     level="project")    # the default
objects.load("objects/quirks.yaml",  level="test")       # highest priority

objects.clear() empties everything; objects.clear(level="test") drops one layer.

5. Live reload while authoring

objects.enable_watch()

With watch mode on, edits to loaded YAML files are picked up on the next alias lookup — tune a selector against a running application without restarting the pytest session. Turn it off in CI (objects.disable_watch() or simply never enable it); production runs should be deterministic.

Where the aliases come from

You don't have to write selectors by hand: dolphin spy --pick prints the selector of any element you Ctrl+Click, and dolphin spy -w "My Window" dumps the whole tree — copy the automation_id / name pairs straight into YAML. See Tracing and Debugging for the spy workflow.

API summary

Call Purpose
objects.load(path, level="project") Load one YAML file
objects.discover(directory="objects") Load every *.yaml in a directory, returns the count
objects.available() All registered aliases
objects.clear(level=None) Forget everything, or one level
objects.enable_watch() / disable_watch() Auto-reload on file change
app.window("alias") Resolve a window alias
win.element("alias") Resolve a child alias of the window's entry

Full reference: dolphin_desktop.objects.