Execution Context in API Fortress

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.

Note: 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: substring payload.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.