Execution Context in API Fortress
Legacy Documentation
You're viewing legacy documentation for API Fortress (deployed via an on-premises container). To view documentation for the new SaaS version of API Fortress — now known as Sauce Labs API Testing and Monitoring (with Sauce Connect tunnels) — see API Testing on the Sauce Labs Cloud.
Preamble: The Nature of Fields
Among the pieces of information you introduce in an API Fortress test some are:
- Taken statically, as strings. These are ingested as they are in the system. Examples:
- the var field in the SET component (the name of the variable itself)
- The type field in an ASSERT-IS component
- Evaluated as expressions. This means that whatever you put in there, it’ll be considered a “piece of code”, something to be evaluated as a logical expression. Examples:
- The expression field in all assertions
- The data or object field in the SET component
Most of the times, they are selectors, as in payload.person.age
- Evaluated as string templates. These are ingested as static strings unless variables are present in it. When variables are present, these get replaced with the values taken from the scope. Examples:
- The content of the COMMENT component
- The body of the postBody component
They are generally used to print a string with variable content as in:
{
"person":{
"age": ${age}
}
}
Data Manipulation in Evaluated Fields
Every evaluated field, such as expressions and variable references in templates, allow data manipulation operations. This means that you’re not limited to just selection of data, but you can manipulate the data to make it what works for your needs.
To do that, you can leverage multiple functions.
Expression Language Extensions
These extensions are unique in the API Fortress engine, and allow you to perform various operations that come handy in your daily work. The full reference is here: https://apifortress.com/doc/expression-language-extensions/
Here are a few examples:
- I need to create a payload that contains a date in milliseconds, that is certainly in the future compared to the current moment. It also needs a unique ID for the request:
{ “futureDate ”: ${D.plusDays(D.nowMillis(),3), “id”: ”${WSCrypto.genUUID()}” }
- I need to pick one random item from an array, and store it in a variable for later use:
<set var=”my_item” object=”payload.myarray.pick()”/>
- I need to put my randomly picked item an a JSON payload, in JSON format:
{ “item”:${my_item.asJSON()} }
Language specific functions
While the extensions can be seen as useful functions for API related tasks, other times you may be in need to perform less specific operations, in a more programmer-like fashion.
Splitting, cutting, searching strings is quite a common thing, as much as accessing specific items in arrays, and so on.
For all these general purpose tasks, API Fortress allows you to use the Groovy programming language in all evaluated fields.
On the cloud, just a subset of these commands are available, while on-prem you get the full language coverage, unless set otherwise in the configuration.
The full semantics documentation is located here: http://groovy-lang.org/semantics.html
Here’s a few typical use cases:
- Take a certain integer from a payload, and store it multiplied by 10:
<set var=”item” object=”payload.counter+10”/>
- Append a suffix to a variable already set:
<set var=”item” value=”${item+’-foobar’}”/>
But this would also work:<set var=”item” value=”${item}-foobar”/>
- Split a string on the comma, and iterate on it with an EACH component:
<each expression=”payload.the\_string.split(‘,’)”>
- Make sure that the prefix (before the - dash) of a certain piece of data is an integer (as in:
“123-foobar”
):<assert-is expression=”payload.id\[0..id.indexOf('-')-1\]” type=”integer”/>
Reads: substringpayload.id
from index zero to the index before the first occurence of'-'
The SET lang Component
The SET component also has a special mode that allows you to write a little Groovy snippet when stuff get rough. It can be accessed by choosing the “Language” mode, and it allows you to write logic like the following:
def items = \[\]
10.times{ it->
items += it
}
return items
The assigned variable will contain an array of integers initialized with the numbers from 0 to 9.
Appendix: string
vs number
Dichotomy
In API Fortress, most built in data structures are strings, such as:
- The variables from the vault
- The variables from the input sets
- The environments
- The variables passed in an API Run call
But also everything generated by the evaluation of a template string, such as:
-
The comments (obviously)
-
The request payloads (obviously)
-
**The value fields**
This is why the SET operation has both a value field and an object (Data) field.
Assuming I’ve set 2 variables like this:
<set var=”data1” value=”5”/>
<set var=”data2” object=”5”/>
And I had to create a third variable incrementing the previous variable by two:
WRONG: <set var=”data3” object=”data1+2”/>
data3
is 52
as data1
is a string
OK: <set var=”data3” object=”data2+2/”>
data3
is 7
as data2
is an integer
For the very same reason:
<set var=”data3” value=”${data2+2}”/>
data3
would indeed store 7
, but as a string
, not a number
. Which may be OK in most cases, unless you need to manipulate the number more.
So what if I wanted to increment data1
by 2
then?
<set var=”data3” object=”data1.toInteger()+2”/>
The toInteger()
method is always there to help you. And if unsure whether a piece of data is already an integer or not, the toInteger()
method won’t complain if the data is an integer already.