Mobile Application Plugin
The plugin provides functionality to test mobile application on real devices, Android Emulators and iOS Simulators.
Installation
-
Copy the below line to
dependencies
section of the projectbuild.gradle
filePlease make sure to use the same version for all VIVIDUS dependencies. Example 1. build.gradleimplementation(group: 'org.vividus', name: 'vividus-plugin-mobile-app', version: '0.6.8')
-
If the project was imported to the IDE before adding new dependency, re-generate the configuration files for the used IDE and then refresh the project in the used IDE.
Locator
By.<locatorType>(<locatorValue>):<visibility>->filter.<filterType>(<filterValue>)
By. prefix is optional. |
-
locatorType
- [mandatory] type of the locator -
locatorValue
- [mandatory] value of the locator -
visibility
- [optional] visibility of element (visible by default) -
filterType
- [optional] type of the filter -
filterValue
- [required if filter type defined] value of the filter
Reusable locators
Feature allows to define custom reusable locator types via properties. These new locator types should rely on one of the already existing ones.
ui.locator.<locatorName>.pattern
ui.locator.<locatorName>.locator-type
-
locatorName
- The name of the reusable locator. Supported characters areA-Z, a-z, -
. -
pattern
- The pattern of the reusable locator. -
locator-type
- The base locator type.
ui.locator.anyAttOrText.locator-type=xpath
ui.locator.anyAttOrText.pattern=//*[@*='%s' or text()='%s']
Given I am on main application page
Then number of elements found by `anyAttOrText(attribute, text)` is = `1`
Given I am on main application page
Then number of elements found by `anyAttOrText(attribute, with comma\, text)` is = `1`
Description | Pattern | Usage | Result |
---|---|---|---|
Single parameter doesn’t require comma escaping. |
|
|
|
The pattern with a single parameter was referenced twice. |
|
|
|
The pattern with a |
|
|
|
The pattern containing |
|
|
|
The pattern without parameters |
|
|
|
The pattern with two parameter placeholders was used with invalid number of parameters. |
|
|
|
Filter Types
Type | Description | Examples |
---|---|---|
|
Get an element by the specified index from a collection of elements found by a locator. Indexes start from 1. |
tagName(div)→filter.index(2) |
|
Filter elements by their text parts. |
tagName(h3)→filter.textPart(Welcome) |
|
Filter elements by their exact text. |
tagName(android.widget.EditText)→filter.text(Welcome) |
|
Filter elements by their attribute values |
|
Locator Types
Type | Platform | Description | Examples |
---|---|---|---|
|
any |
Search the app XML source using xpath (not recommended, has performance issues) |
xpath(//android.widget.TextView[@text='Home']) or By.xpath(//XCUIElementTypeStaticText[@value='Home']) |
|
any |
See Accessibility ID selector strategy |
accessibilityId(menu-toggler) or By.accessibilityId(menu-toggler) |
|
any |
See ID selector strategy |
id(org.vividus:id/menu-toggler) or By.id(menu-toggler) |
|
|
See Class Chain Queries for more details |
iosClassChain(**/XCUIElementTypeCell[$name BEGINSWITH "A"$]) or By.iosClassChain(**/XCUIElementTypeCell[$name BEGINSWITH "B"$]) |
|
|
See iOS Predicate Syntax for more details |
iosNsPredicate(name BEGINSWITH 'A') or By.iosNsPredicate(name BEGINSWITH 'B') |
Properties
The properties marked with bold are mandatory. |
Property Name | Acceptable values | Default | Description | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
hostname |
|
The host of Selenium Grid used to create a new session. |
||||||||
|
username |
|
The username for authentication at Selenium Grid used to create a new session. |
||||||||
|
password |
|
The password for authentication at Selenium Grid used to create a new session. |
||||||||
|
|
|
Whether to rety session creation at Selenium Grid in case of HTTP connect timeout. This flag may be useful when tests are executed via intermittent network connection. |
||||||||
|
ISO-8601 Durations format |
|
The maximum amount of time to wait for HTTP response from Selenium Grid. |
||||||||
|
|
|
The test lifecycle of the mobile application:
An empty property value will lead to the error: "Application session scope is not set". |
||||||||
|
|
|
Whether to publish the application source code on failure or not |
||||||||
|
|
|
If the value is set to |
||||||||
|
ISO-8601 Durations format |
|
Total duration to wait for UI condition |
||||||||
|
ISO-8601 Durations format |
|
Used together with |
||||||||
|
The value between 0 and 1 e.g. 0.75 |
|
Enables compressions of the images published to the report using the specified compression quality. If 1 is set then no compression will be performed. It may help to decrease total report size. |
||||||||
|
|
Depends on the set profile |
Defines the mobile OS to use |
||||||||
|
|
Depends on the set profile |
Defines automation engine to use
|
||||||||
|
|
Depends on the set profile |
Defines whether the tests run on real device
|
||||||||
|
|
Depends on the set profile |
Defines a destination folder on a device for a file being uploaded
|
||||||||
|
|
|
Enable proxy for the whole test run |
||||||||
|
|
|
Enable proxy recording |
||||||||
|
any host name resolving on the machine |
|
Overrides the host which will be used by proxy |
||||||||
|
ports range (e.g., |
|
Ports range which could be occupied for proxy |
||||||||
|
|
|
Overrides the proxy host which will be passed to browser |
||||||||
|
|
|
Enables publishing of attachments with HAR to each failed step. |
||||||||
|
|
|
Whether to disable verification of upstream servers SSL certificates |
||||||||
|
HAR capture types: |
|
List of HAR capture types |
||||||||
|
|
|
Whether to enable MITM proxy for the whole test run |
||||||||
|
|
|
The MITM type using the corresponding certificates. |
||||||||
|
keystore type |
|
The keystore type |
||||||||
|
path to keystore |
|
The relative to |
||||||||
|
password for keystore |
|
The password for keystore |
||||||||
|
keystore alias |
|
The alias for certificate entry in keystore |
Meta Tags
@proxy
- some steps require proxy to be turned on: it can be done by setting the corresponding properties or by switching on this meta tag at story level.
For device configuration, we need to perform the following steps: install CA certificate(download CA certificate from a browserup repository), configure device proxy, and configure the test app to allow proxy in cases of necessity. |
Profiles
iOS
The profile can be enabled by adding mobile_app/ios
to configuration.profiles
property
Default profile configuration
selenium.grid.platform-name=iOS
selenium.grid.automation-name=XCUITest
tvOS
The profile can be enabled by adding mobile_app/tvos
to configuration.profiles
property
Default profile configuration
selenium.grid.platform-name=tvOS
selenium.grid.automation-name=XCUITest
Android
The profile can be enabled by adding mobile_app/android
to configuration.profiles
property
Default profile configuration
selenium.grid.platform-name=Android
selenium.grid.automation-name=UIAutomator2
Local
The local profiles can be used in conjunction with:
-
mobile_app/android
, -
mobile_app/ios
, -
mobile_app/tvos
.
mobile_app/local
The profile simplifies configuration of tests execution against the local Appium 1.x server.
configuration.profiles=mobile_app/local,mobile_app/ios
mobile_app/local2
The profile simplifies configuration of tests execution against the local Appium 2.x server.
configuration.profiles=mobile_app/local2,mobile_app/android
Dynamic variables
Get clipboard text
Gets the text of the system clipboard of simulator or real device
Properties
Property Name | Default | Description |
---|---|---|
|
|
The property is for iOS real devices only and it specifies the WebDriverAgent bundle ID used to get clipboard text. The property value may vary depending on test cloud providers and can be found in the XCode logs. |
${clipboard-text}
Then `${clipboard-text}` is equal to `uarlouski@gmail.com`
Context element rectangle
Context element rectangle dynamic variables are deprecated and will be removed in VIVIDUS 0.7.0, please use Save size and coordinates of element step. |
The set of dynamic variables provides ability to access context element coordinates, width and height.
The variables rely on the contextual approach: it is necessary to switch context to the target element. |
In case of missing search context the error will be logged and -1 will be returned as a result
|
Variable name
Variable name | Description |
---|---|
|
the height of the context element |
|
the width of the context element |
|
the absolute |
|
the absolute |
When I change context to element located by `id(userpic)`
Then `${context-height}` is > `0`
Then `${context-width}` is > `0`
Then `${context-x-coordinate}` is > `0`
Then `${context-y-coordinate}` is > `0`
Context source code
Variable provides source code of the current UI context of the application under test.
${context-source-code}
Given I am on main application page
Then all resources by selector `frame,iframe` from ${context-source-code} are valid
When I change context to element located by `id(linksList)`
Then all resources by selector `a` from ${context-source-code} are valid
Steps
Application management
Start mobile application
Starts mobile application with capabilities from user’s *.properties
files and profiles set by a user.
Given I start mobile application
Start mobile application with capabilities
Starts mobile application with capabilities from user’s *.properties
files and profiles set by a user.
Additionally the step takes a list of capabilities as an argument that overrides globally-defined capabilities.
Given I start mobile application with capabilities:$capabilities
-
$capabilities
- The capabilities to start application with, these capabilities have higher priority than capabilities defined in*.properties
files and profiles.
Given I start mobile application with capabilities:
|name |value|
|bstack:options.networkLogs |true |
|appium:options.clearSystemFiles|false|
Activate mobile application
Activates the existing application on the device/emulator/simulator and moves it to the foreground. The application should be already running in order to activate it.
When I activate application with bundle identifier `$bundleId`
-
$bundleId
-Package name
for Android orBundle identifier
fromPlist.info
for iOS
When I activate application with bundle identifier `com.apple.mobilesafari`
Reinstall mobile application
Removes the mobile application from device/emulator/simulator and installs it again.
When I reinstall mobile application with bundle identifier `$bundleId`
-
$bundleId
-Package name
for Android orBundle identifier
fromPlist.info
for iOS.
The key benefit is that instead of the full remote session recreation (which includes device re-allocation in testing clouds, like SauceLabs, BrowserStack, etc.) achivable via the following example:
When I close mobile application
Given I start mobile application with capabilities:
|name |value|
|fullReset|true |
the step re-uses the current session which significantly improves performance.
When I reinstall mobile application with bundle identifier `vividus-mobile.app`
Terminate mobile application
Terminates the running application on the device/emulator/simulator and navigates to the home device screen (the remote session will not be closed). If the application is not running, new failed assertion is recorded.
When I terminate application with bundle identifier `$bundleId`
-
$bundleId
-Package name
for Android orBundle identifier
fromPlist.info
for iOS of the application to terminate.
When I terminate application with bundle identifier `com.apple.mobilesafari`
Close mobile application
Closes the mobile application and quits the remote session.
When I close mobile application
Run mobile application in background
Runs mobile application in the background for specific period of time and either activates the app after a certain amount of time, or leave the app deactivated (when PT-1S is used). See Appium docs for more details.
When I send mobile application to background for `$period` period
-
$period
- The period of time in ISO-8601 Durations format.
When I send mobile application to background for `PT5S` period
Then number of elements found by `accessibilityId(login-button)` is equal to `1`
Change session settings
Changes the behavior of the Appium session.
When I change Appium session settings:$settings
When I change Appium session settings:
|name |value|
|allowInvisibleElements|true |
Device file management
Upload a file to the device
Uploads a file to the device/emulator/simulator.
When I upload file `$filePath` to device
-
$filePath
- The path of the file to upload to the device.
The destination folder on the device for the uploaded file is configured by mobile-environment.device.folder-for-file-upload property. See more information in the properties section.
|
When I upload file `images/avatar.png` to device
Then the avatar icon is displayed with the uploaded image
Upload the file with data to the device
Upload the file with data to the device/emulator/simulator.
When I upload file with name `$fileName` and data `$data` to device
-
$data
- The data to store as a file. -
$fileName
- The name of the uploaded file.
The destination folder on the device for the uploaded file is configured by mobile-environment.device.folder-for-file-upload property. See more information in the properties section.
|
When I execute HTTP GET request for resource with URL `https://raw.githubusercontent.com/vividus-framework/vividus/master/vividus-tests/src/main/resources/baselines/context.png`
When I upload file with name `context.png` and data `${response-as-bytes}` to device
Then image is displayed in gallery
When I upload file with name `message.txt` and data `This is a message` to device
Then message file is displayed in file explorer
Delete a file from the device
Deletes a file from the device/emulator/simulator.
When I delete file `$filePath` from device
Argument | Platform | Description | Examples |
---|---|---|---|
|
iOS |
The path to an existing remote file on the device. This variable can be prefixed with bundle id, so then the file will be downloaded/deleted from
the corresponding application container instead of the default media folder. Use
|
|
Android |
The full path to the remote file or a specially formatted path, which points to an item inside an app bundle, for example |
|
When I delete file `/sdcard/Pictures/avatar.png` from device
On iOS real device to add or delete photo or video to/from "Camera Roll" you need upload/delete photos or videos to/from /DCIM/100APPLE/ folder and then trigger a rebuild of the "Camera Roll" database by deleting the old databases. You can accomplish it by deleting following files: /PhotoData/Photos.sqlite, /PhotoData/Photos.sqlite-shm, /PhotoData/Photos.sqlite-wal. Restart device is necessary after that. |
On iOS simulator to delete photo or video from "Camera Roll" you need to delete photo or video from /Media/DCIM/100APPLE/ and then trigger a rebuild of the "Camera Roll" database by deleting the old databases. You can accomplish it by deleting following files: /Media/PhotoData/Photos.sqlite, /Media/PhotoData/Photos.sqlite-shm, /Media/PhotoData/Photos.sqlite-wal. And then restart simulator. |
Download the file from the device
Downloads the file from the device/emulator/simulator and saves its content to a variable.
When I download file `$filePath` from device and save its content to $scopes variable `$variableName`
Argument | Platform | Description | Examples |
---|---|---|---|
|
iOS |
The path to an existing remote file on the device. This variable can be prefixed with bundle id, so then the file will be downloaded/deleted from
the corresponding application container instead of the default media folder. Use
|
|
Android |
The full path to the remote file or a specially formatted path, which points to an item inside an app bundle, for example |
|
-
$variableName
- The variable name to store the file content.
When I download file `/sdcard/file.json` from device and save its content to scenario variable `json-file`
Context management
The term "context" or "search context" refers to the area within which the element lookup is performed. By changing the context during the process of locating elements, it is possible to significantly streamline the creation and maintenance of tests. This helps to build more efficient and effective test cases, reducing the time spent interacting with unnecessary elements or searching the entire screen for the desired element.
Change context
Resets the context, finds the element by the given locator and sets the context to this element if it’s found.
When I change context to element located by `$locator`
Deprecated syntax (will be removed in VIVIDUS 0.7.0):
When I change context to element located `$locator`
-
$locator
- The locator used to find the element to change context to.
Then number of elements found by `id(header)` is equal to `1`
When I change context to element located by `id(table)`
Then number of elements found by `id(header)` is equal to `0`
Change context within current context
Finds the element by the given locator in the current context and sets the context to this element if it’s found.
When I change context to element located by `$locator` in scope of current context
Deprecated syntax (will be removed in VIVIDUS 0.7.0):
When I change context to element located `$locator` in scope of current context
-
$locator
- The locator used to find the element to change context to.
Then number of elements found by `id(header)` is equal to `1`
When I change context to element located by `id(table)`
Then number of elements found by `id(header)` is equal to `0`
When I change context to element located `id(first-row)` in scope of current context
Then number of elements found by `id(table)` is equal to `0`
Reset context
Resets the context if it was set previously.
When I reset context
Then number of elements found by `id(header)` is equal to `1`
When I change context to element located by `id(table)`
Then number of elements found by `id(header)` is equal to `0`
When I reset context
Then number of elements found by `id(header)` is equal to `1`
Elements validation
Validate elements number
Validates the context contains the number of elements matching the specified comparison rule.
Then number of elements found by `$locator` is $comparisonRule `$quantity`
-
$locator
- The locator used to find elements. -
$comparisonRule
- The comparison rule. -
$quantity
- The expected number of the elements.
Then number of elements found by `xpath(./a)` is equal to `5`
Text content manupulations
Save the text of an element
Finds the element by the given locator and saves its text into a variable.
When I save text of element located by `$locator` to $scopes variable `$variableName`
-
$locator
- The locator used to find the element whose text content will be saved. -
$scopes
- The comma-separated set of the variables scopes. -
$variableName
- The name of the variable to save the text content.
When I save text of element located by `id(header)` to scenario variable `heading-text`
Save the text of the context
Saves the text of the context element into a variable.
An error is thrown if the context is not set to the element. |
When I save text of context element to $scopes variable `$variableName`
-
$scopes
- The comma-separated set of the variables scopes. -
$variableName
- The name of the variable to save the text content.
When I change context to element located by `id(username)`
When I save text of context element to scneario variable `username`
Switch to Web view by name
Switches context to a web view with name that matches the rule (see Automating hybrid apps for more information). Also, Appium capabilities for iOS and Android are available for the fine-tuning configuration.
When I switch to web view with name that $comparisonRule `$value`
-
$comparisonRule
- The web view name comparison rule. -
$value
- The value to find the target web view.
Then number of elements found by `xpath(html)` is equal to `0`
When I switch to web view with name that contains `vividustestapp`
Then number of elements found by `xpath(html)` is equal to `1`
Switch to native context
Switches context to a mobile native context. See Automating hybrid apps for more information.
When I switch to native context
Then number of elements found by `xpath(html)` is equal to `1`
When I switch to native context
Then number of elements found by `xpath(html)` is equal to `0`
Tap on element
Taps on the element located by the locator.
The atomic actions performed are:
-
press on the element;
-
release.
When I tap on element located by `$locator`
-
$locator
- Locator.
When I tap on element located by `accessibilityId(menu-toggler)`
Tap on element with duration
Taps on the element located by the locator with the specified duration.
The atomic actions performed are:
-
press on the element;
-
wait for the duration;
-
release.
When I tap on element located by `$locator` with duration `$duration`
-
$locator
- Locator. -
$duration
- The duration between an element is pressed and released in ISO-8601 Durations format.
When I tap on element located by `accessibilityId(menu-toggler)` with duration `PT0.5S`
Double tap on element
Performs double tap on the element located by the locator.
The step is supported for Android and iOS platforms. |
When I double tap on element located by `$locator`
-
$locator
- Locator.
When I double tap on element located by `accessibilityId(increment)`
Press key
Presses iOS keys or Android keys.
When I press $key key
-
$key
- The key to press.
When I press Home key
Long press key
Performs long press of iOS keys or Android keys.
to modify long press duration for iOS and tvOS you could use mobile-application.long-press-duration property.
|
When I long press $key key
-
$key
- The key to perform long press action.
When I long press Home key
Press keys
Presses a sequence of iOS keys or Android keys.
When I press keys:$keys
-
$keys
- The keys to press.
When I press keys:
|key|
|P |
|a |
|s |
|1 |
|$ |
Type text sequentially
Types the provided text
All the characters will be treated as is and passed sequentially. To send special key like HOME please use Press keys.
|
When I type text `$text`
-
$text
- The text to type.
When I type text `pas1$`
Type text in a field
Types the text into the element located by the locator.
The existing text is re-written by the text passed into the step. |
The atomic actions performed are:
-
type text into the element;
-
hide keyboard.
For iOS real devices the hide keyboard action works only for
XCUIElementTypeTextField elements and skipped for XCUIElementTypeTextView
elements, in case of XCUIElementTypeTextView element tap outside the text view
is performed to close the keyboard.
|
When I type `$text` in field located `$locator`
-
$text
- The text to type into the element. -
$locator
- Locator.
When I type `Bob` in field located `accessibilityId(username)`
Type text and keep keyboard opened
Only types text into the element. The keyboard hiding is skipped.
When I type `$text` in field located `$locator` and keep keyboard opened
-
$text
- The text to type into the element. -
$locator
- Locator.
When I type `Bob` in field located `accessibilityId(username)` and keep keyboard opened
Clear field
Clears the field located by the locator.
The atomic actions performed are:
-
clear the field;
-
hide keyboard.
For iOS real devices the hide keyboard action works only for
XCUIElementTypeTextField elements and skipped for XCUIElementTypeTextView
elements, in case of XCUIElementTypeTextView element tap outside the text view
is performed to close the keyboard.
|
When I clear field located `$locator`
-
$locator
- Locator.
When I clear field located `accessibilityId(username)`
Clear field and keep keyboard open
Only clears the field located by the locator. The keyboard hiding is skipped.
When I clear field located `$locator` and keep keyboard open
-
$locator
- Locator.
When I clear field located `accessibilityId(username)` and keep keyboard open
Swipe to an element
Swipes to an element in either UP
, DOWN
, LEFT
or RIGHT
direction with
the specified swipe duration.
The step takes into account the current context. If you need to perform swipe on the element, you need to switch the context to this element. |
Properties
-
mobile-application.swipe.limit
- defines max numbers of swipes to perform (if it’s reached the swipe process is stopped and the error is thrown) -
mobile-application.swipe.stabilization-duration
- defines a duration to wait after swipe until view becomes stable -
mobile-application.swipe.vertical.x-position
- defines a vertical swipex
axis position in percentage from0
to100
, where0
corresponds tox=1
and100
corresponds tox = mobile screen width - 1
, default value is0
-
mobile-application.swipe.horizontal.y-position
- defines a horizontal swipey
axis position in percentage from0
to100
, where0
corresponds toy=1
and100
corresponds toy = mobile screen height - 1
, default value is50
When I swipe $direction to element located by `$locator` with duration $swipeDuration
-
$direction
- The direction to swipe:UP
,DOWN
,LEFT
orRIGHT
. -
$locator
- Locator. -
$swipeDuration
- The swipe duration in ISO-8601 Durations format.
Then number of elements found by `accessibilityId(end-of-screen)` is equal to `0`
When I swipe UP to element located by `accessibilityId(end-of-screen)` with duration PT1S
Then number of elements found by `accessibilityId(end-of-screen)` is equal to `1`
Scenario: Switch slides
When I change context to element located by `accessibilityId(carousel)`
Then number of elements found by `accessibilityId(slide 2)` is equal to `0`
When I swipe LEFT to element located by `accessibilityId(slide 2)` with duration PT1S
Then number of elements found by `accessibilityId(slide 2)` is equal to `1`
Execute sequence of touch actions
Executes the sequence of touch actions.
When I execute sequence of touch actions: $actions
-
$actions
- The table with actions to execute.Table 1. Possible actions type
argument
Argument example TAP
Element locator or empty
By.id(Name)
TAP_AND_HOLD
Element locator or empty
By.id(Name)
MOVE_TO
Element locator
By.id(username)
MOVE_BY_OFFSET
Point, that specifies x and y distance to move from its current position or from upper left corner (0,0), if the pointer has not previously been moved
(10, 15) where x is 10 and y is 15
RELEASE
empty
WAIT
Duration
PT1S - wait 1 second
RELEASE action releases the finger at the current touch location. For example, it can be used in the following
sequence of actions:`TAP_AND_HOLD` → MOVE_BY_OFFSET → RELEASE
|
When I execute sequence of touch actions:
|type |argument |
|TAP_AND_HOLD |By.id(Hello World)|
|MOVE_BY_OFFSET|(0,200) |
|RELEASE | |
Zoom in/out
Performs zoom in/out
The step takes into account the current context. If you need to perform zoom on the element, you need to switch the context to this element. |
Properties
Property Name | Acceptable values | Default value | Description |
---|---|---|---|
|
size in percentage |
|
The size of the top part of the context to be excluded from zoom area |
|
size in percentage |
|
The size of the bottom part of the context to be excluded from zoom area |
|
size in percentage |
|
The size of the right part of the context to be excluded from zoom area |
|
size in percentage |
|
The size of the left part of the context to be excluded from zoom area |
The indent percentage value should be from The sum of The sum of |
mobile-application.zoom.indent.top=30
mobile-application.zoom.indent.bottom=30
mobile-application.zoom.indent.right=20
mobile-application.zoom.indent.left=20
Step
When I zoom $zoomType context
-
$zoomType
- The type of zoom:IN
orOUT
When I zoom in context
When I wait until element located by `xpath(<welcomeMessageXpath>)` disappears
When I zoom out context
When I wait until element located by `xpath(<welcomeMessageXpath>)` appears
Select date in date picker
Selects a next or previous picker wheel value in date picker
-
Only
iOS
platform is supported. -
The target element must be of type
XCUIElementTypePickerWheel
.
When I select $direction value with `$offset` offset in picker wheel located `$locator`
-
$direction
- The direction to search the value:NEXT
orPREVIOUS
. -
$offset
- The ofset to pick from a middle of the wheel, see Select Picker Wheel Value guide. -
$locator
- The locator to findXCUIElementTypePickerWheel
element.
When I select next value with `0.1` offset in picker wheel located `xpath(//XCUIElementTypePickerWheel)->filter.index(3)`
Recording iOS Performance metrics
Records performance metrics of iOS application. It is based on the Instruments utility distributed by Xcode which provides a number of built-in analyses and measurements. See Capturing Performance Data for Native iOS Apps and Getting Started with Instruments for more information.
Appium server should be started with the --relaxed-security flag. This is because Instruments can gather data from the system as a whole, not just the AUT. (It’s thus a security risk to expose potentially sensitive system information to Appium sessions running from a remote client). |
Archive with results contains *.trace file which could be opened by XCode. There is possibility to parse this file using XCode’s utility xctrace and use generated data in tests |
When I start recording `$instrument` metrics
When I stop recording `$instrument` metrics and save results to file `$path`
-
$instrument
- The instrument of Xcode Instruments utility. Some useful instruments: Time Profiler, Leaks, File Activity, etc. -
$path
- The path to the file to save an archive with collected data.
When I start recording `Time Profiler` metrics
!-- set of actions to measure performance
When I stop recording `Time Profiler` metrics and save results to file `${outputDirectory}/time_profiler.zip`
Set slider value
iOS
Sets the slider value in percents.
-
The accuracy of setting the slider value is not guaranteed and may vary depending on the device screen resolution.
-
The target element must be of type
XCUIElementTypeSlider
. -
The percent number must be between 0 and 100 inclusively.
When I set value of iOS slider located `$locator` to `$percent` percents
-
$locator
- The locator to findXCUIElementTypeSlider
element. -
$percent
- The target value of the slider in percents.
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `90` percents
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `70` percents
When I set value of iOS slider located `xpath(//XCUIElementTypeSlider)` to `80` percents
Android
Sets the slider value to the number relatively to the slider leftmost side of its range.
-
The step is expected to set accurate value without deviations.
-
The target element must be of type
android.widget.SeekBar
. -
The number must be greater than or equal to 0.
-
Make sure the passed number does not exceed the right limit of the slider, this may lead to unexpected failure.
When I set value of Android slider located `$locator` to `$number`
-
$locator
- The locator to findandroid.widget.SeekBar
element. -
$number
- The number to set on the slider
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `13`
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `25`
When I set value of Android slider located `xpath(//android.widget.SeekBar)` to `2`
Taking screenshot steps
Take screenshot and save it to the file
Takes a screenshot and saves it to the file at the specified path.
The full path to the file with the taken screenshot is posted to logs and report. |
When I take screenshot and save it to file at path `$screenshotFilePath`
Deprecated syntax (will be removed in VIVIDUS 0.7.0):
When I take screenshot and save it to folder `$screenshotFilePath`
-
$screenshotFilePath
- The path to the file to save the screenshot, the allowed values are:-
an absolute path to the file, e.g.
C:\Windows\screenshot.png
; -
a relative path (it is resolved from the current working directory, e.g.
screenshot.png
.
-
When I take screenshot and save it to file at path `${screenshot-directory}/start-page.png`
Wait for element appearance
Waits for appearance of the element by the locator.
It’s forbidden to use Visibility types in the locator. |
When I wait until element located by `$locator` appears
-
$locator
- Locator.
When I wait until element located by `name(welcome-image)` appears
Wait for element disappearance
Waits for disappearance of the element by the locator.
If the element doesn’t exist on the page/context, the step will immediately complete successfully. Checking the element on the page (if needed) should be done in a separate step (e.g. Wait for element appearance or Validate elements). |
It’s forbidden to use Visibility types in the locator. |
When I wait until element located by `$locator` disappears
-
$locator
- Locator.
When I wait until element located by `name(welcome-image)` disappears
Wait for element with specified state using polling interval
Waits for an element with the specified state to be found using the specified timeout with polling interval.
When I wait `$duration` with `$pollingDuration` polling until element located by `$locator` becomes $state
When I wait `PT10S` with `PT1S` polling until element located by `id(element-to-hide)` becomes not visible
Wait for expected elements number
Waits for the expected number of elements located by locator.
In order to wait for invisible elements one rely on Visibility types. |
When I wait until number of elements located by `$locator` is $comparisonRule $number
-
$locator
- Locator. -
$comparisonRule
- The comparison rule. -
$number
- The expected number of the elements.
When I wait until number of elements located by `tagName(img)` is equal to `5`
When I wait until number of elements located by `tagName(img):1` is equal to `5`
Wait for element to stop moving
Waits for element with the specified locator to stop moving.
An element is considered moving when its coordinates (position) are changing. For example, an animated GIF is not a moving element unless it changes position. |
When I wait until element located by `$locator` stops moving
-
$locator
- Locator.
When I wait until element located by `id(submitForm)` stops moving
Verify elements state
Verifies if the number of elements located by locator matches the number condition and all of them are in the desired state.
If you describe number condition as equal to 5 in case if there are 10 elements by this locator and only 5 of them in the desired state. You will get two failed assertions. The first one about number condition violation. The second one about state check failure. |
In case when Visibility types are used and checked state are equal (For an example ':i' and 'NOT_VISIBLE') exception will be thrown. In such cases please use step: Validate elements number. Contradictory visibility parameters (locator - ':i' and checked state - 'VISIBLE') are also not allowed. |
Then number of $state elements found by `$locator` is $comparisonRule `$quantity`
-
$state
- State -
$locator
- Locator. -
$comparisonRule
- The comparison rule. -
$quantity
- The expected number of elements.
Then number of VISIBLE elements found by `tagName(img)` is = `1`
Saves the attribute value of the context
Saves the attribute value of the context element into a variable.
Step will throw an error if the context element is not set. |
When I save `$attributeName` attribute value of context element to $scopes variable `$variableName`
-
$attributeName
- The name of an element attribute. -
$variableName
- The name of the variable to save the attribute value.
When I change context to element located by `id(username)`
When I save `innerText` attribute value of context element to SCENARIO variable `username`
Save the attribute value of the element
Saves the attribute value of the element located by locator into a variable.
When I save `$attributeName` attribute value of element located by `$locator` to $scopes variable `$variableName`
Deprecated syntax (will be removed in VIVIDUS 0.7.0):
When I save `$attributeName` attribute value of element located `$locator` to $scopes variable `$variableName`
-
$attributeName
- The name of an element attribute. -
$locator
- Locator. -
$variableName
- The name of the variable to save the attribute value.
Save the attribute value of the element
When I save `innerText` attribute value of element located by `id(username)` to SCENARIO variable `username`
Save number of elements
Saves number of elements located by locator into a variable.
When I save number of elements located by `$locator` to $scopes variable `$variableName`
Deprecated syntax (will be removed in VIVIDUS 0.7.0):
When I save number of elements located `$locator` to $scopes variable `$variableName`
-
$locator
- Locator. -
$variableName
- The name of the variable to save the number of elements.
When I save number of elements located by `tagName(a)` to scenario variable `numberOfLinks`
Then `${numberOfLinks}` is equal to `1`
Save size and coordinates of element
Saves the information about the size of an element and its coordinates relative to the viewport.
When I save coordinates and size of element located by `$locator` to $scopes variable `$variableName`
-
$locator
- Locator. -
$variableName
- The name of the variable to save the coordinates and size of an element which can be accessed on the variable name using dot notation (please see examples section):Attribute Description x
the
x
coordinatey
the
y
coordinateheight
the
height
of the elementwidth
the
width
of the element
When I save coordinates and size of element located by `tagName(img)` to scenario variable `rect`
Then `${rect.height}` is equal `400`
Then `${rect.width}` is equal `400`
Then `${rect.x}` is equal `200`
Then `${rect.y}` is equal `8`
Element existence during the time period
Validates the element located by the locator has existed for the period specified by the duration.
The actions performed by the step:
-
check the search context is set,
-
search for the element to validate existence (this search may include wait for element appearance if it’s configured),
-
validate the element has presented for the period specified by the duration.
Then element located by `$locator` exists for `$duration` duration
-
$locator
- The Locator to find an element. -
$duration
- The period of time the element should have existed in ISO-8601 Durations format.
Then element located by `id(banner)` exists for `PT5S` duration
Wait until element has text matching regular expression
Waits until an element with the specified locator has text that matches the provided regular expression.
When I wait until element located by `$locator` has text matching `$regex`
-
$locator
- The Locator of the element which text to check. -
$regex
- The regular expression used to validate the text of the element.
When I wait until element located by `id(indicator)` has text matching `\d+`
Verify elements order
Gets a collection of elements by locator and checks that they are sorted by their text in the specified order. The collection should have more than 1 element with not empty text, otherwise the step fails.
Then elements located by `$locator` are sorted by text in $sortingOrder order
-
$locator
- Locator. -
$sortingOrder
Plain | Readable | Description |
---|---|---|
ASCENDING |
ascending |
Verify that elements are sorted in ascending order |
DESCENDING |
descending |
Verify that elements are sorted in descending order |
CASE_INSENSITIVE_ASCENDING |
case-insensitive ascending |
Verify that elements are sorted in case-insensitive ascending order |
CASE_INSENSITIVE_DESCENDING |
case-insensitive descending |
Verify that elements are sorted in case-insensitive descending order |
Given I am on page with URL `https://grocery.by`
When I click on element located by `id(a-z)`
Then elements located by `xpath(//span[@id='item-to-purchase'])` are sorted by text in ascending order
Scan barcode
Scan a barcode and save its value to the variable with the specified name. Only the first founded barcode will be scanned.
Supported Code Formats
1D product | 1D industrial | 2D |
---|---|---|
|
|
|
Actions performed at this step:
-
Takes a viewport screenshot
-
Scans a barcode from the screenshot and save its value to the variable
When I scan barcode from screen and save result to $scopes variable `$variableName`
-
$variableName
- The name of the variable to save the value of the barcode.
When I scan barcode from screen and save result to scenario variable `qrCodeLink`
Then `${qrCodeLink}` is equal to `https://www.example.com`
Perform steps while elements exist
Executes the steps while the found elements exist.
To avoid infinite loops the iterationLimit parameter is used. If iteration’s limit reached the step will fail. |
When I find $comparisonRule `$number` elements `$locator` and while they exist do up to $iterationLimit iteration of$stepsToExecute
Alias:
When I find $comparisonRule '$number' elements $locator and while they exist do up to $iterationLimit iteration of$stepsToExecute
-
$comparisonRule
- The comparison rule. -
$number
- The number of elements to find. -
$locator
- Locator. -
$iterationLimit
- The maximum number of iterations to perform. -
$stepsToExecute
- The ExamplesTable with a single column containing the steps to execute.
When I find >= `0` elements `xpath(//*[@class='menu enabled'])` and while they exist do up to 10 iteration of
|step |
|When I click on element located by `id(disable)`|
Execute JavaScript with arguments
Executes JavaScript via JavascriptExecutor. Step executes the script either without any arguments or with String
or Object
argument types.
When I execute javascript `$script` with arguments:$arguments
-
$script
- The JavaScript code to execute. -
$arguments
- The examples table with set of arguments and their type:-
value
- The value of the argument. -
type
- The type of the argument. Eitherstring
orobject
.
-
When I execute javascript `document.querySelector('#assistant').remove()` with arguments:
When I execute javascript `sauce:inject-image` with arguments:
|value |type |
|iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=|string|
When I execute javascript `sauce:throttleCPU` with arguments:
| value | type |
| {"rate" : 4} | object |
Execute JavaScript and save result.
Executes JavaScript code and saves result into variable.
When I execute javascript `$jsCode` and save result to $scopes variable `$variableName`
-
$jsCode
- Any JavaScript code. In order to save a result return statement should be used. -
$variableName
- The variable name to script execution result.
Given I am on page with URL `https://vividus-test-site-a92k.onrender.com/`
When I execute javascript `return JSON.stringify(window.performance.timing)` and save result to scenario variable `timings`
Then number of JSON elements from `${timings}` by JSON path `$.connectStart` is = 1
Scan barcode from context
Scan a barcode from the specified context and save its value to the variable with the specified name. If context not set - takes a screenshot of the current screen. Only the first found barcode will be scanned.
Supported Code Formats
1D product | 1D industrial | 2D |
---|---|---|
|
|
|
Actions performed at this step:
-
Takes a screenshot of the specified context. If it’s not set - takes a screenshot of the current screen (viewport and system bars)
-
Scans a barcode from the screenshot and save its value to the variable
When I scan barcode from context and save result to $scopes variable `$variableName`
-
$variableName
- The name of the variable to save the value of the barcode.
When I change context to element located by `xpath(//android.view.ViewGroup[@resource-id='qrContainer'])`
When I scan barcode from context and save result to scenario variable `qrCodeLink`
Then `${qrCodeLink}` is equal to `https://www.example.com`
Proxy Steps
Check the number of HTTP requests
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level.
The actions preformed by the step:
-
extract HTTP messages from the recorded proxy archive
-
filter out the HTTP messages with the response status code
302 Moved Temporarily
-
find HTTP requests matching the provided HTTP methods and the URL regular expression
-
check that the total number of the found HTTP messages satisfies the desired condition
In case of failure the full HTTP archive (HAR) is attached to the report.
Then number of HTTP $httpMethods requests with URL pattern `$urlPattern` is $comparisonRule `$number`
-
$httpMethods
- The comma-separated HTTP methods to filter by -
$urlPattern
- The regular expression to match HTTP request URL -
$comparisonRule
- Comparison Rule -
$number
- The number to compare with
Then number of HTTP GET, POST requests with URL pattern `http://httpbin\.org/get` is equal to `1`
Capture HTTP message
Save the HTTP message part from the HTTP request with given URL-pattern into the variable with specified name and the scopes.
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level.
The actions preformed by the step:
-
extract HTTP messages from the recorded proxy archive
-
filter out the HTTP messages with the response status code
302 Moved Temporarily
-
find HTTP requests matching the provided HTTP methods and the URL regular expression
-
check that total number of the found HTTP messages is equal to
1
-
save the HTTP message part to the specified variable
In case of failure the full HTTP archive (HAR) is attached to the report.
When I capture HTTP $httpMethods request with URL pattern `$urlPattern` and save $httpMessagePart to $scopes variable `$variableName`
-
$httpMethods
- The "or"-separated set of HTTP methods to filter by, e.g.GET or POST or PUT
. -
$urlPattern
- The regular expression to match HTTP request URL. -
$httpMessagePart
- The HTTP message part to save. One of:-
URL
- The request URL. -
URL query
- The request URL query parameters. -
request data
- The request data includes the following keys:-
query
- The URL query is stored as a collection of key and value pairs, where key is the name of the query parameter and value is the list of query parameter values. The query parameter values are accessible via zero-based index. -
requestBody.mimeType
- The MIME type of posted data, the variable will not be saved if MIME type is not present. -
requestBody.text
- The posted data as plain text, the variable will not be saved if the request body is not present. -
requestBodyParameters
- The form data parameters are stored as a collection of key and value pairs, where key is the name of the form parameter and value is the list of form parameter values. The form parameter values are accessible via zero-based index. -
responseStatus
- The response status, the variable will not be saved if the response is not present.
-
-
response data
- The response data includes the following keys:-
responseBody.mimeType
- The MIME type of response data, the variable will not be saved if MIME type is not present. -
responseBody.text
- The response data as plain text, the variable will not be saved if the response body is not present.
-
-
-
$variableName
- The variable name to save the HTTP message part.
Given I start mobile application
When I capture HTTP GET or POST request with URL pattern `.*/search.*=vividus` and save URL to scenario variable `URL`
Then `${URL}` is equal to `https://www.google.com/search?q=vividus`
Given I start mobile application
When I capture HTTP GET request with URL pattern `.*/search.*=vividus` and save URL query to scenario variable `query`
Then `${query.q[0]}` is equal to `vividus`
Then `${query.q}` is equal to `[vividus]`
Then `${query}` is equal to `{q=[vividus]}`
Given I start mobile application
When I capture HTTP GET request with URL pattern `https://www.google.com/search?q=vividus` and save request data to scenario variable `data`
Then `${data.query}` is equal to `{}`
Then `${data.requestBodyParameters}` is equal to `{delivery=, custtel=, comments=, custemail=, custname=}`
Then `${data.requestBody}` is not equal to `null`
Then `${data.responseStatus}` is equal to `200`
Given I start mobile application
When I capture HTTP GET request with URL pattern `https://www.google.com/search?q=vividus` and save request data to scenario variable `data`
Then `${data.responseBody.text}` is equal to `{"status": "ok"}`
Then `${data.responseBody.mimeType}` is equal to `application/json`
Wait for the HTTP request
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Waits for the HTTP requests matching the provided HTTP methods and URL regular expression. If no HTTP request is sent and wait timeout is reached, then the step will fail.
When I wait until HTTP $httpMethods request with URL pattern `$urlPattern` exists in proxy log
-
$httpMethods
- the "or"-separated HTTP methods to filter by, e.g. 'GET or POST or PUT' -
$urlPattern
- the regular expression to match HTTP request URL
Given I start mobile application
When I wait until HTTP GET or POST request with URL pattern `https://www.google.com/search?q=vividus` exists in proxy log
Then number of HTTP GET or POST requests with URL pattern `https://www.google.com/search?q=vividus` is equal to `1`
Add headers to the HTTP request
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Add headers to the proxied HTTP request satisfying the desired condition
When I add headers to proxied requests with URL pattern which $comparisonRule `$url`:$headers
-
$comparisonRule
- String comparison rule -
$url
- The input value of URL to filter by -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I add headers to proxied requests with URL pattern which is equal to `https://www.google.com/search?q=vividus`:
|name |value |
|testName1|testValue1|
|testName2|testValue2|
Given I start mobile application
Then a JSON element from '${response}' by the JSON path '$.headers' is equal to '
{
"Testname1": "testValue1",
"Testname2": "testValue2"
}
'ignoring extra fields
Clear the recordings
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. The step clears the HTTP requests and responses recorded by the proxy
When I clear proxy log
Given I start mobile application
When I clear proxy log
Then number of HTTP GET requests with URL pattern 'https://www.google.com/search?q=vividus' is equal to `0`
Clear the mocks
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. The step clears previously created mocks
When I clear proxy mocks
When I mock HTTP responses with request URL which CONTAINS `vividus` using response code `200`, content `#{loadResource(page.html)}` and headers:
|name |value |
|Content-Type|text/html|
When I clear proxy mocks
Given I start mobile application
Then number of elements found by `id(sw)` is = `0`
Mock the HTTP response by methods with content
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Mocks HTTP response by methods with a provided content
No actual request will be executed. Short-circuited response will be returned. |
When I mock HTTP $httpMethods responses with request URL which $comparisonRule `$url` using response code `$responseCode`, content `$payload` and headers:$headers
-
$httpMethods
- The "or"-separated set of HTTP methods to filter by, e.g.GET or POST or PUT
. -
$rule
- String comparison rule -
$url
- The input value of URL to filter by -
$code
- The response status code -
$content
- The content to send within a response -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I mock HTTP POST responses with request URL which CONTAINS `example` using response code `202`, content `#{loadResource(mocked-example.json)}` and headers:
|name |value |
|Content-Type|application/json|
Mock the HTTP response with content
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Mocks HTTP response with a provided content
No actual request will be executed. Short-circuited response will be returned. |
When I mock HTTP responses with request URL which $comparisonRule `$url` using response code `$responseCode`, content `$payload` and headers:$headers
-
$rule
- String comparison rule -
$url
- The input value of URL to filter by -
$code
- The response status code -
$content
- The content to send within a response -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I mock HTTP responses with request URL which CONTAINS `example.com` using response code `200`, content `#{loadResourceAsByteArray(page.html)}` and headers:
|name |value |
|Content-Type|text/html|
Mock the HTTP response without content
This step requires proxy to be turned on. It can be done in properties or by switching on @proxy meta tag at the story level. Mocks HTTP response
No actual request will be executed. Short-circuited response will be returned. |
When I mock HTTP responses with request URL which $comparisonRule `$url` using response code `$responseCode` and headers:$headers
-
$rule
- String comparison rule -
$url
- The input value of URL to filter by -
$code
- The response status code -
$headers
- The ExamplesTable representing the list of the headers with columns "name" and "value" specifying HTTP header names and values respectively
When I mock HTTP responses with request URL which CONTAINS `example.com` using response code `404` and headers:
|name |value|
|Content-Length|0 |
Change network connection
Turns ON/OFF network connection.
To be able to use this step in the cloud testing platform, review the documentation related to simulating the mobile network conditions on the selected platform. |
When I turn $toggle `$connectionName` network connection
-
$toggle
- The modes of the toggle:ON
orOFF
. -
$connectionName
- The name of the network connect to toggle.
Connection name | Supported platforms | Description |
---|---|---|
|
Android emulators, Android and iOS real devices |
Wi-Fi connection |
|
Android emulators, Android and iOS real devices |
Mobile Data connection |
|
Android real devices, Android emulators |
Airplane Mode |
|
Android real devices, Android emulators |
Mobile Data and Wi-Fi connections |
For iOS real devices: to return to the application you must use the step:
|
When I turn OFF `WIFI` network connection
When I turn OFF `WIFI` network connection
When I activate application with bundle identifier `my-application-bundle-id`
Change device screen orientation
Changes the device screen orientation.
When I change device screen orientation to $orientation
-
$orientation
- The device screen orientation, eitherportrait
orlandscape
.
When I change device screen orientation to portrait