...
This article will guide the reader through the process of creating their first test script and provide examples for each type of script element available for use in their test scripts.
Table of Contents |
---|
Your First Script
When you first access the Hurricane service you will see the list of previously created test definitions.
...
Code Block | ||
---|---|---|
| ||
{ "headers": [], "steps": [ { "name": "", "type": "Request", "method": "GET" "url": "", "headers": [], "body": null, "actions": [ ] } ] } |
...
Code Block | ||
---|---|---|
| ||
{ "headers": [], "steps": [ { "name": "Hello World", "type": "Request", "method": "GET" "url": "http://localhost/hello", "headers": [], "body": null, "actions": [ ] } ] } |
...
Just before the test is run, the {{ServerDomain}} portion of the “url” field will be replaced with the value of our property. In this case the “url” field value would be rewritten to “http://localhost/hello”. If the test was run against a QA environment, the value might be overwritten to “http://myqaserver”. Now our test can be pointed at any number of different servers at run time without having to change the test definition itself.
...
Warning |
---|
Nesting property references is not supported. The results will be indeterminate. |
Sending a Request Body
Let’s create a new test definition using our boiler plate content. This time we’re going to send data to an endpoint that will echo back the text that was sent to it:
Code Block | ||
---|---|---|
| ||
{
"headers": [],
"steps":
[
{
"name": "Echo",
"type": "Request",
"method": "POST"
"url": "{{ServerDomain}}/echo",
"headers": [],
"body":
{
"text": "My text content"
},
"actions":
[
]
}
]
} |
Short Form vs Long Form Body
The example above defines the body content using the short-form. Since the content is in Json format, the content can simply be written as the value of the “body” property. This also has the benefit that the Content-Type header will automatically be added when the test is run. However, if the content being sent isn’t in json format (i.e. XML) the long form must be used. The following script uses the long form to send the same body content:
Code Block | ||
---|---|---|
| ||
{
"headers": [],
"steps":
[
{
"name": "Echo",
"type": "Request",
"method": "POST"
"url": "{{ServerDomain}}/echo",
"headers":
[
{
"name": "Content-Type",
"value": "application/json"
}
],
"body": "{\r\n\"text\": \"My text content\"\r\n}",
"actions":
[
]
}
]
} |
Notice how special characters like line returns and quotes are escaped using ‘\'. If the content contains ‘\’ prior to being escaped, the ‘\’ is escaped by doubling up the '\’ to “\\”. Also, notice that the Content-Type header has to be explicitly added to the header section of this request (or could be added to the top-level header property that is inherited by all steps. Another consideration when deciding to use the short vs long form is the use of properties and variable placeholders. If the placeholder is contained in a quoted property name or value, the short form can be used without issue. However, if the placeholder is expected to be replace with structured content and the use of the placeholder is not quoted, the script definition will no longer be valid Json.
Making Multiple Requests
A test case may require making multiple requests. The top level “steps” property of the test definition is an array that can contain any number of test steps that will be executed in the order they appear when the test is run. Let’s combine our previous test definitions together:
Code Block | ||
---|---|---|
| ||
{
"headers": [],
"steps":
[
{
"name": "Hello World",
"type": "Request",
"method": "GET"
"url": "{{ServerDomain}}/hello",
"body": null,
"actions":
[
]
},
{
"name": "Echo",
"type": "Request",
"method": "POST"
"url": "{{ServerDomain}}/echo",
"headers":
[
{
"name": "Content-Type",
"value": "application/json"
}
],
"body": "{\r\n\"text\": \"My text content\"\r\n}",
"actions":
[
]
}
]
} |
When this test is run, each session will make a call to the hello world endpoint followed by a call to the echo endpoint. After the second request returns, the session will start over and run both again until the test ends. Metrics for each request are tracked separately. Using the top-level “steps” array property makes it easy to run multiple requests in order. However, you may want separate groups of requests or other steps together to help organize a complex test. This can be done by using the sequence or random step which will be covered later in the tutorial.
Using Test Variables
Let’s update our test definition to capture the response from the hello world request and pass it to the echo request. First we need to capture the response and place it into a variable. We do this by adding a Json action to our first request:
Code Block | ||
---|---|---|
| ||
{
"headers": [],
"steps":
[
{
"name": "Hello World",
"type": "Request",
"method": "GET"
"url": "{{ServerDomain}}/hello",
"body": null,
"actions":
[
{
"name": "Capture Result",
"type": "json",
"extractionPairs":
[
{
"jsonPath": "text",
"variableName": "myvar"
}
]
}
]
},
{
"name": "Echo",
"type": "Request",
"method": "POST"
"url": "{{ServerDomain}}/echo",
"headers":
[
{
"name": "Content-Type",
"value": "application/json"
}
],
"body":
{
"text": "My text content"
},
"actions":
[
]
}
]
} |
All actions have these properties:
name - The name of the action
type - The type of the action (json, cookie). For this example, we’re using the json action to capture information from a json formatted response
The json action has an additional property:
extractionPairs - An array of path and variable name pairs that defines which json properties to extract and what variable to store them in
jsonPath - A dot separated list of json property names to extract
variableName - The name of the variable to store the value in. This name is then used in a placeholder in later requests
Our hello world endpoint returns a json document with a single property:
Code Block | ||
---|---|---|
| ||
{
"text": "Hello World!"
} |
We reference this property in the jsonPath property. We also give our variable a name of “myvar” so we can use it later. Let’s go ahead and update our test definition to use our new variable to send “Hello World!” to the echo endpoint:
Code Block | ||
---|---|---|
| ||
{
"headers": [],
"steps":
[
{
"name": "Hello World",
"type": "Request",
"method": "GET"
"url": "{{ServerDomain}}/hello",
"body": null,
"actions":
[
{
"name": "Capture Result",
"type": "json",
"extractionPairs":
[
{
"jsonPath": "text",
"variableName": "myvar"
}
]
}
]
},
{
"name": "Echo",
"type": "Request",
"method": "POST"
"url": "{{ServerDomain}}/echo",
"headers":
[
{
"name": "Content-Type",
"value": "application/json"
}
],
"body":
{
"text": "[[myvar]]"
},
"actions":
[
]
}
]
} |
Notice that the format of a variable reference is different from a property in that instead of surrounding the property name with “{{“ and “}}” you use “[[“ and “]]” for variables. When the session runs, it first makes the request to the hello world endpoint and then grabs the value from the “text” property of the response and stores it in the “myvar” variable. When the echo request is made, the placeholder reference “[[myvar]]” is replaced with the value stored in the “myvar” variable; “Hello World!” in our case.
Each time the session starts over, any variables captured during the previous run are removed to ensure nothing is carried over between loops. The only exception to this are variables captured or modified in the Initial and Maintenance scripts. Those variables are shared with all sessions and can only be modified by those scripts. If you attempt to update the value of a global variable within the Main script, and error will be raised.