Test action types
Overview
Test actions represent atomic pieces of logic which execute a single test step (e.g. click a web UI element or make an HTTP request to execute an API call). In the test automation literature test actions are typically referred to as "keywords" and the corresponding test practice is called "keyword-driven" testing. Test actions execute sequentially, in the order they were specified in the test definition. Each test action can take 0 or more input arguments and may produce one or more output values that can be used in subsequent actions.
OpenTest defines three types of test actions: regular actions, script actions and macro actions.
Regular actions
Most regular test actions you’ll need to use are provided as part of the core OpenTest package, but new actions can be added with custom extensions. Regular test actions are implemented as Java classes that inherit from the TestAction
base class.
To call a regular test action, use the following syntax:
- description: This is a sample test step
action: org.getopentest.actions.SampleAction
args:
argument1: value1
argument2: value2
The three properties of a regular test action are:
description (optional): A human-readable description of what the action is looking to accomplish in the context of your particular test. The action description is used in logs and test execution reports, so providing a clear and accurate description makes it a lot easier to understand the execution flow and troubleshoot failed tests.
action: This is the fully qualified name of the Java class that implements the test action logic (package name and class name, separated by a dot). For example, to run the
Click
action from theorg.getopentest.selenium
package, you would useorg.getopentest.selenium.Click
.args (optional): The arguments passed to the test action. While some test actions are very simple and need no arguments (e.g. the Selenium SwitchToLastWindow action), most test actions require additional information in order to execute successfully, like the locator of a web UI element to click on, or the text to type in a textbox. Arguments can be simple data types like strings or numbers, but can also be complex types, like collections of name-value pairs (hash maps).
Script actions
JavaScript code can be inserted anywhere in the test flow by using script actions. Just like the other test action types, script actions can also provide a description
property that explains what the action does. The JavaScript code to execute must be provided as a string value in the script
property of the test action. Here’s a script action that delays execution for 2 seconds using the $delay
function exposed by OpenTest:
- description: Delay execution for two seconds
script: $delay(2000)
For non-trivial scripts, the YAML multiline syntax can be used to organize the script neatly over multiple lines. In YAML, multiline strings can be represented using the "|" (pipe) character:
- description: Click buttons with IDs "button1" to "button100"
script: |
for (var buttonNo = 1; buttonNo <= 100; buttonNo++) {
$runAction("org.getopentest.selenium.Click", {
locator: { id: "button" + buttonNo }
});
}
Macro actions
A macro action may contain any sequence of test actions (both regular and script actions, as well as other macro actions) that is stored in a separate file and can be called from multiple tests or from multiple places in the same test. The purpose of macro actions is to help avoid code duplication and increase readability, so they play a similar role with the one functions play in most programming languages.
For example, most applications require the user to log in before executing the work that is specific to a particular test case. The proper way to perform the user authentication would be to create a macro action called "Login" and then call that macro at the beginning of each test that requires authentication, using this syntax:
- macro: Login
To create the Login
macro, add a new file named Login.yaml
in the macros
subdirectory of your test repo, with the following content:
description: Perform the steps necessary to authenticate a user
actions:
- description: Call the authentication API
action: org.getopentest.actions.HttpRequest
args:
url: https://some.url.here/authenticate?user=john&password=mypasswd
verb: GET
# ... perform other necessary actions here
Like all test actions, macros may take arguments as input and can produce output values. To pass arguments to a macro action, you can use the same syntax as for a regular action:
- macro: Login
args:
username: john_doe
password: sk67E8qL
To read the arguments that a macro was called with, you can use the $macroArgs
JavaScript function (more details here). In order to write an output value from a macro action, you can add them as properties of the $macroOutput
object (more details here).
Let’s assume we have an HTTP API that we must call to authenticate to a web service, which returns this JSON data: {"authToken": "kf74F43KL9gSd9dP"}
. The sample code below is a macro action that makes use of the username
and password
arguments and create an output value named authToken
, containing the authetication token returned by the HTTP API. The code also makes use of some other features like the local data store, the $output
and the $format
APIs, which are documented separately, so don’t worry if you don’t understand all the code in the snippet at this point.
description: Authenticate the user
actions:
- script: |
// Build the authentication URL and store it in a variable
var authenticationUrl = $format(
"https://some.url.here/authenticate?user={0}&password={1}",
$macroArgs.username,
$macroArgs.password)
- description: Call the authentication API
action: org.getopentest.actions.HttpRequest
args:
url: authenticationUrl
verb: GET
- script: $macroOutput.authToken = $output.body.authToken;
Once we have this macro, we can call it in all the tests that require authentication with the following syntax:
- macro: Login
args:
username: john_doe
password: sk67E8qL
- script: $log("The authentication token is " + $output.authToken)
Writing macros usually requires slightly more advanced skills and an above-average familiarity with the system under test, so it’s recommended that they are implemented by the more experienced members of a team. Building a solid set of macros can significantly speed up test development, make the test suite easier to maintain and has a big impact on the long-term success of the test automation effort.