# Loops
Loops in Virtuoso provide a simple yet powerful way to repeat test steps within checkpoints. This feature enables you to loop over checkpoints without the need for complex scripting, eliminating the need for manual duplication of repetitive steps, streamlining test automation workflows while maintaining efficiency and clarity.
# Who should use this feature?
- Users who need to validate multiple UI elements dynamically (e.g., image carousels, product bundles, retry operations) or require loops that automatically adapt to test data variations.
- Teams looking to streamline test workflows without writing complex scripts.
# Key benefits
- Simplified test design: Configure loops with a simple toggle between Fixed and Conditional modes.
- Efficiency: Loops adapt dynamically to test conditions, skipping unnecessary steps.
- Customization: Users can define their own execution logic via conditions.
# How it works
Loops are configured within the context of a specific journey and are not properties of checkpoints themselves. This means that setting a loop on a checkpoint in one journey has no effect on the same checkpoint in any other journey. Each journey's loop configuration is independent, ensuring that loops apply only to individual checkpoints within that particular journey and do not extend across multiple journeys.
Virtuoso offers two modes for configuring loops — Fixed and Conditional — to accommodate different testing needs. Whether you need a specific number of iterations or dynamic behavior based on conditions, loops make it easy to streamline repetitive tasks and adapt to varying test scenarios.
# 1. Fixed mode
- The checkpoint executes a specific number of times (up to 10).
- Users can enter a static number or use a variable to define iterations.
# 2. Conditional mode
- The checkpoint executes based on a Variable-based or JavaScript expression condition.
- Users can enter a static number or use a $variable to define the max number of iterations (up to 10).
- The condition is evaluated before each iteration, and the loop continues as long as it evaluates to
true
or until the maximum iteration count is reached. - You can choose to skip condition evaluation on the first iteration by enabling the corresponding option.
- This ensures that the first iteration always runs, with the condition being evaluated only from the second iteration onward.
- Note: The first iteration is included in the maximum iteration count.
# Configuring loops
Loops can be configured in one of two modes. This section walks you through the steps to enable and configure loops.
# Step 1: Enable loops on a checkpoint
- Open a journey and navigate to the checkpoint where loops are needed.
- On the checkpoint options, select the option Add loop.
# Step 2: Select loop mode
- Choose either Fixed or Conditional mode.
# Fixed mode configuration
- Select Fixed as the loop type.
- In the Loop for field, enter a number (max 10) or a variable (e.g.,
$iterations
). - Click Save to apply the settings.
# Conditional mode configuration
- Select Conditional as the loop type.
- Enter a maximum iteration count (max 10).
- Select the type of condition and configure the condition: Variable-based or JS expression.
- If you want the first iteration to always be executed, choose Skip condition evaluation on first iteration option.
- Click Save to apply the settings.
Loops limitations
Loops are limited to a maximum of 10 iterations. This limit is enforced in both modes of loops, Fixed and Conditional.
# Variable-based
With this option you can define simple conditions using an intuitive and self-explanatory interface to determine whether the checkpoint loop iteration should be executed. You start by specifying a variable using the syntax $variable
. Then, there are six operator choices available for defining the condition:
- is defined: When selecting the is defined operator, the condition will evaluate to true if the variable is defined and has a value. By using the is defined operator, you can execute an iteration based on the presence of a specific variable.
- is not defined: The is not defined operator functions as the inverse of the is defined operator. It evaluates to true if the specified variable is not defined or does not have a value. This operator allows you to execute an iteration when a particular variable is absent or empty.
- is empty: The is empty operator will execute the iteration if a variable is defined, but has no value. Note that the iteration will fail if the variable is undefined.
- is not empty: The is not empty operator will execute the iteration if a variable is defined, and has any value. As above, the iteration will fail if the variable is undefined.
- equals: The equals operator allows you to compare the values of two variables, or the value of a variable against a fixed value. If the values are equal, the condition will evaluate to true, and the iteration will be executed.
- is not equal to: Similar to the equals operator, the is not equal to operator compares the values of two variables, or the value of a variable against a fixed value. If the values are not equal, the condition will evaluate to true, and the iteration will be executed.
Supported syntax
To define a condition variable, you can optionally use the dot notation to access an object's property ($variable.prop1.prop2
). For using the bracket notation, please use the "Advanced" option explained below. When using a fixed value as the condition's right operand, it has to be either a number (e.g. 42.5
) or a string (e.g. English
).
Here is how you should configure it:
- Enter a the left operand by selecting or typing a
$variable
. - Select the operator.
- (Required for binary operators) Enter a the right operand by selecting or typing a
$variable
orvalue
.
# JS expression
This option allows you to execute the checkpoint loop iterations based on the evaluation of a JavaScript (JS) expression. If the JS expression evaluates to a truthy value, the iteration will be executed. Otherwise, it will be skipped. This option requires more technical knowledge, but covers some edge cases not supported by the Variable-based option.
Here is how you should configure it:
- In the Condition field, enter a JavaScript expression to control execution.
- Example:
$response?.status !== 200
(loop will continue until the API returns200
).
- Example:
# Skipping checkpoint execution due to loop configuration
A checkpoint may not be executed if:
- The iteration count is set to
0
(or evaluates to0
using a variable). - The condition in a Conditional loop evaluates to
false
on the first run. - The Skip condition evaluation on first iteration is selected and it's the first iteration of the loop.
# Example use case
A test should run only if a specific value is present in a dropdown. If the value doesn’t exist, the entire checkpoint is skipped.
# Key use cases
# 1. Testing carousel images
A user needs to verify images, titles, and links in a carousel. Instead of duplicating steps, loops iterate through stored values for each image variation.
# 2. Scroll bar testing
A tester needs to validate if a scroll bar is shown inside a currency dropdown in cases where it has at least 10 currencies. Since the initial number of currencies may vary, a checkpoint first checks the list length and adds a currency if needed. This repeats until 10 currencies exist, ensuring accurate UI validation.
# 3. Handling product bundles and add-ons
A test must handle different numbers of add-ons per product bundle, as defined in test data. A loop automates the addition of items based on the number of add-ons listed in the test dataset, eliminating manual repetition.
# Authoring with loops
Authoring a looped checkpoint shares the same capabilities as authoring any other checkpoint.
We also offer a few utilities that can help you during the creation of steps inside a loop:
- Step details per iteration: You can view step information for each iteration of a test step, allowing you to fully understand what happened in each iteration.
- Loop condition evaluation: The first step of each iteration will also display the result of the loop condition.
- Access the iteration number: If you need to know the iteration you’re in within a looped checkpoint step, you can use the variable
$VIRTUOSO_CONTEXT.loopIteration
. This variable contains the current iteration number. This variable contains the current iteration number, which starts at 1. - Breakpoints on iterations: You can set breakpoints for specific steps in one or more iterations as needed. Additionally, you can quickly add or remove breakpoints for all iterations using the all action.
- Loop summary: You can quickly inspect the outcome of each iteration by hovering over the Loop iteration outcome.
Notes & Considerations
- Conditional loops iterations: In conditional loops, execution rows are pre-allocated for the defined maximum number of iterations. If fewer iterations are needed, some rows remain unused and are skipped.
- Scope of loops: Loops apply only to individual checkpoints and do not extend across multiple checkpoints.
- No nested loops: You cannot place one loop inside another.
- Checkpoint skipping: If the loop condition evaluates to
false
before the first iteration, the checkpoint is skipped. - Library checkpoints: Loops configuration are not persisted in Library Checkpoints, as looping is tied to a specific journey.
- Condition handling: If a Conditional loop’s condition never evaluates to
false
, execution stops at 10 iterations to prevent infinite loops.