Define elements

Name the things your tests touch, choose good values for them, and add fallbacks that survive redesigns.

Beginner, about 8 min

An element is a name for something on screen, plus one or more values that tell Optics how to find it. Steps refer to elements by name (${sign_in}), so when the app changes, you update the element once and every test follows.

Write elements#

Elements live in any CSV whose header starts with Element_Name,Element_ID. The project template puts them in test_data/elements.csv.

test_data/elements.csv
Element_Name,Element_ID
sign_in,//*[@resource-id='com.birch.shop:id/login']
sign_in,Sign in
cart_icon,cart_icon.png
search_bar,Search Birch
email,[email protected]

To give an element several values, repeat its name on more rows. Optics tries them top to bottom. You can also add more columns whose names start with Element_ID, such as Element_ID_text or Element_ID_image, and fill them in on the same row:

test_data/elements.csv
Element_Name,Element_ID,Element_ID_text,Element_ID_image
sign_in,//*[@resource-id='com.birch.shop:id/login'],Sign in,sign_in.png

Both layouts mean the same thing. Use whichever is easier to read for your team. Empty cells are ignored.

Choose the kind of value#

Optics decides what a value is from how it looks:

WriteOptics treats it asExample
Starts with /, // or (XPath, looked up in the UI tree//*[@resource-id='login']
Plain wordsText: UI tree first, then OCR on a screenshotSign in
text_only: then wordsText, OCR onlytext_only:Sign in
Ends in .png, .jpg, .jpeg or .bmpAn image to match on a screenshotcart_icon.png
css=, #id, .class or tag[attr]A CSS selector. Works with Playwright, not Selenium#login-button
Starts with android. or XCUIA class nameandroid.widget.Switch

XPath#

An XPath is a path through the app's UI tree. It's the fastest and most precise kind of value, and the best first choice when the app has stable ids:

  • Android: //*[@resource-id='com.birch.shop:id/login']
  • iOS: //XCUIElementTypeButton[@name='Sign in']
  • Web: //button[@id='login']

To pick the second of several matches, wrap the XPath in parentheses and add an index: (//android.widget.Button)[2].

Text#

Plain text matches an element showing that text, or with that accessibility label. It's the most readable kind of value, and it survives layout changes. If the text isn't in the UI tree, for example because it's drawn inside an image or a game canvas, Optics reads the screenshot with OCR, as long as a text detection engine is enabled.

Text matching in the UI tree tolerates small differences. To require exact matches, set strict_element_match: true in config.yaml.

Images#

An image value is the file name of a cropped picture of the element. Put the picture anywhere in the project folder (the templates use test_data/input_templates/) and refer to it by file name only. Image matching is the slowest kind and needs an image detection engine. Use it for icons with no text or id. Find elements by text and image shows how to capture a good picture.

Values to avoid#

id: values, such as id:login, aren't supported by any element source and always fail. Use an XPath on the id instead.

Find the right locator#

  • **In optics live**, try a value with press_element or assert_presence before you write it down. The history line shows whether it worked and how it was found.
  • Android and iOS: Appium Inspector shows each element's id, text and XPath.
  • Web: right-click an element in Chrome and choose Inspect.
  • Any platform: the Get Interactive Elements keyword lists the buttons, fields and text on the current screen. In optics live, run get_interactive_elements and open the JSON file it writes to the output folder.

Pick one of several matches#

When the same text appears more than once, index picks a match, counting from 0:

modules/modules.csv
module_name,module_step,param_1,param_2
Add Second Product,Press Element,Add to cart,index=1

To look in one part of the screen instead, use an area of interest.

Keep data in elements too#

Elements can hold any value a step needs, not only locators: an email address, a search term, a URL. Keeping them together means one file holds everything that changes between environments.

To keep a password out of log files, start its value with @:, for example password,@:correct-horse. Optics masks it as **** in logs and types it without the prefix on Appium, Selenium and Bluetooth devices. Playwright types the prefix too, so don't use @: with Playwright.

To put a line break or tab inside a value, write \n or \t. Write \\ for a literal backslash.

See also#