How to write a good test
The msg.ZenTestAI platform turns natural-language descriptions into executable test steps. The quality of the test is therefore largely the quality of the prompts you write. The prompts should be clear, concise and use one of the supported actions per step.
When the runner executes your test, it first uses an AI classifier to map each step description to one of the supported actions. The better your prompt aligns with one of these actions and the clearer your description of the target element, the more reliably the step is executed.
Write test cases so that a person who has never seen the application could follow them step by step. The closer your prompt is to a "click-by-click" instruction, the easier it is for the AI agent to understand and execute.
Guidelines
You will get the best results when you follow these guidelines:
- Think in terms of the DOM, not the screenshot. Actions are executed against the technical DOM tree (elements, labels, attributes), not against pixels. The page under test should be reasonably accessible for automation — at least labels, roles, IDs or stable class names. Pure-image UIs (canvas, custom-rendered) are hard to drive.
- Align prompts with the supported actions. The classifier maps your description to exactly one action per step. If your prompt mixes actions (e.g. "click and then type"), split it into two steps.
- Avoid ambiguous verbs. "Select value 'test'" can mean clicking, picking from a dropdown, or highlighting text. Be specific: "click the menu item …", "select from the dropdown …".
- Use quotes around important values.
Type "John Doe" into the text field labeled "Name"is much easier to parse than the unquoted version. - One step = one action. A step is executed in isolation. Prompts like "I expect that something changes" or "the value should be different" can't be evaluated because the agent has no memory of the previous state. Compare against concrete values instead.
- Don't strip
[[parameter]]placeholders or${…}template expressions. Both are recognized by the classifier and resolved at execution time. See Parameters, Macros and Dynamic Calculations.
Right next to each step there is an Explain action (in the step's overflow menu). It shows exactly how the AI agent understood your step — which action it picked, which element it expects to interact with, and which value will be used. Use it whenever a step does not behave as expected, before changing the prompt.
Actions
The runner supports the following actions. Every step is classified into exactly one of them.
| Action | Description |
|---|---|
| Clicking | Single, double, right, back or forward click on an element. |
| Checkboxes / Radios / Switches | Set a checkbox, radio button or switch to a specific state (uses Click under the hood). |
| Typing | Type text into a text field; clear, replace or append; pick a date in a date picker. |
| Expecting | Assert something about the page, URL, tabs, downloads, or a parameter value. |
| Selecting from a dropdown | Pick one or more values from a dropdown / combobox. |
| Hovering | Move the mouse over an element (e.g. to reveal a tooltip). |
| Focusing | Move the keyboard focus to an element. |
| Scrolling | Scroll to an element, to the page edges, by a number of pixels, or inside a container. |
| Drag & Drop | Drag a source element and drop it onto a target element. |
| Slider / Range | Move a slider to a specific value; range sliders are set as two separate steps. |
| File Upload | Upload one or more files (or a folder, packaged as .zip) into a file-input element. |
| Key combination | Press a key or key combination (e.g. Ctrl+S). |
| Wait | Wait for a fixed time or until a condition is met. |
| Switch browser tab | Switch to, create or close a browser tab. |
| Change URL / Navigation | Navigate to a URL, change path/hash, go back/forward, reload, or open a previously downloaded file. |
| Condition | Execute steps based on a single condition. |
| Condition Group | Execute one of several mutually-exclusive branches (if / else-if / else). |
| Loop / Repeat | Repeat steps a fixed number of times or until a condition holds. |
| Remember parameter value | Read a value from the page and store it in a parameter for later steps. |
| Go to transaction (SAP only) | Open an SAP Web GUI transaction by its code (e.g. SE11). |
Each section below explains the action in detail.
Clicking
Use this action to click on any element on the page.
The AI agent will:
- Decide how to click. Supported variants: single-click (default), double-click, triple-click, right-click, middle-click, back-click and forward-click (mouse buttons). Mention the variant in your prompt if you need anything other than a single click.
- Find the element from your description.
- Click it.
By default the step fails if the element is not clickable (disabled, not visible, behind a modal). You can change this default per page in the Application Settings so that the agent ignores unclickable elements instead of failing.
Clicking inside a text field places the caret at the end of the existing text. Selecting text inside a text field is not supported.
A few browser elements cannot be driven through the Click action:
- Native HTML
<select>dropdowns (use Selecting from a dropdown instead). - Native browser prompts (file-open dialogs, JS prompts, …). The only supported case is uploading via File Upload.
- Browser-level right-click context menus.
Examples:
Click on the "Save" buttonDouble-click on the "Save" buttonClick on the text field labeled "Name" inside the section "General"
Checkboxes / Radios / Switches
Setting a checkbox, radio button or switch is internally a Click action with the target state attached. The agent will first check the current state and only click if a change is needed.
You can use either an explicit activate / deactivate phrasing or simply toggle:
Activate the checkbox labeled "Male"Deactivate the switch labeled "Dark Mode"Enable the radio button "Age 10-15"Toggle the switch "Notifications"
Recognized verbs: activate, deactivate, enable, disable, tick, untick, check, uncheck, toggle.
Typing
Use this action to type text into an input or textarea. The step fails if the target element is not typeable.
A Type prompt must contain at least:
- The value to type.
- The element to type into.
By default the existing text is cleared before typing, and the input is not confirmed (Enter is not pressed) — focus is just removed afterwards. You can override the defaults in your prompt:
Clear the field before typing(or keep it)… and press Enterto confirm the valueReplace "John" in the input field labeled "Name" with "Jane"— to replace a substringClear the text field labeled "Name"— by setting the value to empty
You can change the defaults of these settings per page in the Application Settings.
A good default for confirm via Enter depends heavily on the application. Many apps implicitly expect Enter after typing. Configure this once per page in Application Settings instead of adding "and press Enter" to every step.
Asking the agent to type and then also press Enter via a separate Key combination step is unnecessary and discouraged. The Type action handles confirm-via-Enter natively when you mention it in the same step.
Examples:
Type "John Doe" into the text field labeled "Name"Type "John Doe" into the text field labeled "Name" and press EnterReplace the text "John" in the input field labeled "Name" with "Jane"Clear the text field labeled "Name"Type "John Doe" into the text field labeled "Name" without clearing the field
All element actions consider the full DOM tree, including elements outside the current viewport. Depending on the per-page setting, the agent will automatically scroll to bring the target element into view.
Date pickers
For date and time fields, prefer Type over Click. The Type action understands common date formats and uses the date-picker mode automatically when it is more reliable than typing key-by-key.
Type "01.01.2010" into the date picker labeled "Date of Birth"Select "01.01.2010" in the date picker for the field "Date of Birth"← still classified as Type
Expecting
Use the Expect action for all assertions. The agent uses generative AI to evaluate your assertion against a screenshot of the page (or the URL / tab / downloads / parameter context). Pure technical assertions (specific HTML attributes, CSS classes, raw DOM trees) are not supported — msg.ZenTestAI performs black-box testing.
You can assert about:
- Visual — anything that can be seen in a screenshot (visibility, colors, layout, presence of text/icons, table row counts, …).
- URL / browser tabs — current URL, page title, number of open tabs, the URLs of tabs.
- Downloads — number of downloaded files, file names.
- Static facts — anything derivable from parameter values without inspecting the page.
You can focus the agent on a sub-section by mentioning the parent element in the prompt (e.g. "in the table", "in the section General").
Phrasing rules — the classifier rewrites every Expect to start with "I expect that …". Phrases like "I cannot see X" are interpreted as "I expect X to not be visible" — don't worry about inverting yourself.
Combine assertions about the same target into one step, but split assertions about different targets into separate steps:
- ✅ One step: "I expect that the button is red and enabled" (one target — the button).
- ✅ One step: "I expect that the menu contains the entries Save and Cancel" (one target — the menu).
- ❌ One step: "The button is red and the table has 10 rows" — split into two.
Examples:
Expect that the text "Hello World" is visibleExpect that the license plate of the car contains the text "MUC-123"Expect that the URL of the page is "https://www.msg-systems.com"Expect that the page contains a table with 5 rowsExpect that the section "General" contains a text field labeled "Name"
Scrolling and assertions interact subtly. Assertions are based on a screenshot, so you usually don't need to scroll first — the agent will do the right thing:
- If a parent element is given (e.g. a table), a full screenshot of that element only is taken.
- If a single element is given, the agent scrolls to it and screenshots the page.
- If nothing is given, the agent screenshots the whole page up to ~3000×3000 px (potentially beyond the viewport).
Selecting from a dropdown
Use this action to select one or more values from a dropdown / combobox.
The prompt must contain at least:
- The value(s) to select.
- The dropdown to select from.
The classifier needs an explicit hint that this is a dropdown — words like dropdown, combobox, select field trigger it. A bare "Select 'green' for color" is ambiguous and is more likely to be classified as a Click.
Do not use the Click action for HTML native <select> elements. They can't be driven by clicks — use this action instead.
You can pick 1…n values; for multi-comboboxes the agent triggers the value as a toggle (it does not differentiate select vs. deselect — the result depends on the previous state). Combine multiple selections from the same combobox into one step.
For multi-comboboxes the agent clicks the combobox once at the end to close it. For regular dropdowns it assumes the dropdown closes itself after selection — if your component does not, follow with a Click to close it.
Examples:
Select "Germany" from the dropdown labeled "Country"Select "Germany" and "France" from the dropdown labeled "Country"
Hovering
Move the mouse over an element (e.g. to reveal a tooltip) and keep it there.
Examples:
Hover over the "Save" buttonHover over the text field labeled "Name"
Focusing
Move the keyboard focus to an element. The element must be focusable.
Examples:
Focus the "Save" buttonFocus the text field labeled "Name"
Scrolling
Scrolling supports several modes:
- Scroll to an element —
Scroll to the element labeled "Footer". - Scroll to the top / bottom of the page —
Scroll to the bottom of the page. - Scroll by a fixed number of pixels —
Scroll down the page by 500 pixels. - Scroll relative to an element —
Scroll down by 500 pixels relative to the element labeled "Footer". - Scroll inside a container —
Scroll to the right side of the menu labeled "Navigation" by 500 pixels.
Pixel-based and top/bottom scrolls only work if the entire page is scrollable (i.e. the browser scrollbar is on the page itself). Scrolling inside a section requires you to name the parent element.
Drag & Drop
Drag a source element and drop it onto a target element. Both must be named in the same step.
Drag & Drop does not support:
- Pixel-based offsets (by design — pixel offsets become flaky when the layout changes).
- Dragging between different browser tabs.
Always describe a target element, not a position.
Examples:
Drag the element labeled "Row 1" to the element labeled "Table 2"Drag the element labeled "Row 1" to the element labeled "Table 2" and drop it at the end of the table
Slider / Range selection
Move a slider (range input) to a specific value. The prompt must contain:
- The slider reference (e.g. "the slider in the section X labeled Y").
- The target value.
The step fails if the value cannot be reached (min/max limits, step constraints, …).
Range sliders with two thumbs must be set as two separate steps, one per thumb.
Examples:
Set the slider in section "test", labeled "hello" to 50Set the lower thumb of the range slider in section "test", labeled "hello" to 50. Set the upper thumb to 100.(as two steps)
Only sliders built on the standard, accessible HTML pattern are supported. For non-standard slider implementations, fall back to plain Drag & Drop.
File Upload
Upload one or more files (or a folder, packaged as .zip) into a file-input element.
The prompt must contain:
- The file(s) or folder to upload (by name or description).
- The target file-input element.
The file(s) must first be attached to the step using Files (Upload / Download) in the step's advanced settings, and they must be available in the tenant under Additional Functions → File Upload. Maximum file size: 10 MB per file.
- If you assign one file to the step, the agent uses it regardless of how you describe it.
- If you assign multiple files, a dedicated agent matches your description (or list of names) to the right file(s).
- To upload a whole folder, package it as a
.zip— the runner extracts it on upload.
Examples:
Upload the file "test.txt" to the file upload element labeled "Upload"Upload the files "image1.png" and "image2.png" to the gallery upload
Mention "upload" only if you can see an actual file-input element on the page (typically identifiable by a Browse button). Some applications hide the file input behind a custom UI; in that case you must use Click on the visible trigger and assign the file to that step instead. You cannot interact with the OS-level browse dialog itself — it is handled by the browser, not the page.
Key combination
Press a key or key combination on the page. Keys are joined with +. The key combination is sent in the context of the previously focused element.
Examples:
Press "Ctrl" + "C"Press "Ctrl" + "Shift" + "A"Press "Enter"
Use Change URL — not Key combination — for browser-level navigation. Going back, forward, or reloading is a different action even if you would do it with a keyboard shortcut as a user. Writing "Press Alt+Left" will not reliably navigate back; write "Go back" instead.
Likewise, you do not need a Key combination step to confirm a typed value with Enter — that is handled by Typing automatically when you mention it.
Wait
Wait for a fixed amount of time or until a condition is met. Provide the time (with optional unit — default is milliseconds) or a clear description of what to wait for.
Wait for 5 secondsWait for 500 millisecondsWait until the loading spinner disappearsWait for the "Save" button to be enabled
The maximum wait is 180 seconds (3 minutes). Longer waits are clamped.
Explicit waits are often a smell. msg.ZenTestAI already waits automatically for the page to be stable before each step (see Auto Waiting). If you find yourself adding manual waits, look at the underlying timing issue first.
Switching browser tabs
Switch to, open or close a browser tab. The detailed behavior is covered in Tab Handling. Mention the tab by 1-based index or by URL / title.
Change URL / Navigation
Navigate the current browser tab. Supports five variants:
1. Navigate to a URL — absolute or partial. Hash-only / path-only changes work.
Navigate to "https://www.msg-systems.com"Change the path of the URL to "/about"Change the hash of the URL to "#contact"
2. Navigate back — equivalent to the browser's Back button.
Go backNavigate to the previous page
3. Navigate forward — equivalent to the browser's Forward button.
Go forward
4. Reload — refresh the current page.
Reload the pageRefresh
5. Open a downloaded file — open a file previously downloaded during the same execution, in a new tab.
Open the downloaded file "report.pdf"Open the last downloaded file
When opening a downloaded file without specifying a name, the most-recently-downloaded file is opened. The file opens in a new browser tab — you may need to switch back manually.
Opening a downloaded file is only possible if the file was downloaded during the current test execution.
Condition
Execute steps based on a single boolean check. A Condition step needs:
- The condition to evaluate.
- The step(s) to execute when the condition is true (as substeps).
- Optionally, the step(s) to execute when the condition is false.
The condition itself can be evaluated against either the current screenshot (visual check) or static facts (URL, parameter values, number of downloads, …).
Conditions add execution branches and make tests harder to read. If you find yourself writing many conditions, consider splitting into two simpler tests instead.
Examples:
If the text "Hello World" is visible, click on the "Save" button else click on the "Cancel" buttonIf the URL is "https://www.msg-systems.com", click on the "Save" buttonIf the number of downloads is 5, click on the "Save" buttonIf the text "Hello World" is visible, click on the "Save" button and type "John Doe" into the text field labeled "Name"
Condition Group
Use a Condition Group when you have multiple mutually-exclusive branches ("if A do X, else if B do Y, else do Z"). The classifier creates one Condition Group step with one Condition substep per branch. Each Condition substep contains the actions for that branch.
Example:
If the value displayed is higher than 5, press the backward button until it is 5; otherwise press the forward button until it is 5.
Resolves to: one Condition Group → two Condition substeps → each with a Loop substep → each with a Click substep.
Looping / Repeating
Repeat a step (or sequence of steps) a fixed number of times or until a condition holds. The Loop step needs:
- The exit condition or repeat count.
- The substep(s) to repeat.
Examples:
Click on the "Save" button 5 timesClick on the "Save" button until the text "Hello World" is visibleClick the next button until the displayed counter is 5
A loop is repeated at most 10 times. After 10 iterations the agent assumes the action is not achievable and aborts the test.
Remembering parameter values
Read a value from the page (or the URL, an attribute, a count, …) and store it in a parameter so that later steps can reference it via [[parameterName]].
Remember the number of rows in the table as parameter [[ROW_COUNT]]Remember the page title in parameter [[CURRENT_TITLE]]
See Parameters and test-data for how stored parameters interact with variants, macros and assertions.
Go to transaction (SAP only)
Available only when the page under test is identified as SAP Web GUI. Navigates to the given SAP transaction by code.
Go to transaction SE11Open SAP transaction SE16
For other applications the same wording is classified as a Click on a navigation element instead.
Parameters, macros and template expressions
Three syntaxes are recognized inside step descriptions and field values and are left alone by the classifier:
| Syntax | Meaning | More |
|---|---|---|
[[parameterName]] | Reference to a parameter, resolved per variant or by a previous Remember step. | Parameters |
${=macroKeyword(args)} | Macro call — runs a reusable function and inlines the returned value. | Macros |
${ free-text expression } | Dynamic calculation evaluated by an AI agent (e.g. ${current date in DD.MM.YYYY}). Use sparingly — prefer macros. | Dynamic Calculations |
All three can be combined inside a single step description (for example using a parameter as a macro argument: ${=global_addDays([[OFFSET]])}).