Configuration¶
Directory Structure¶
An etr
test module is similar to a wtools
module structure but it has an etr.yaml
file
instead of wscript
in the root:
<root> # module root
|-- etr.yaml # main configuration file
`-- src # source directory for test files
A minimum example using Robot Framework:
<root>
|-- etr.yaml
`-- src
`-- tests.robot
Contents of etr.yaml
:
version: "1.0"
plugins:
- etr.plugins.robot
robot:
tests:
- src/tests.robot
Main Configuration File¶
The etr.yaml
configuration file has the following basic schema:
version: "1.0"
# Optional config, by default it's True
randomize: True|False
# List of plugins to load
plugins:
- <plugin>
Then each loaded plugin might have their own schema with a root node. For example the robot plugin
etr.plugins.robot
has the following schema:
version: "1.0"
plugins:
- etr.plugins.robot
robot:
tests:
- src/my-test.robot
- src/my-other-test.robot
Note
By default test execution order, as specified in the configuration file, is randomized.
For robot this means that one should write the robot test suite files without expectation
that other test suites have been executed. This has the benefit of being able to execute
a subset of tests without them breaking which is useful for speed.
If this is infeasible the randomize: False
can be set.
Plugins¶
Most of the heavy lifting in etr
is done with plugins, where the core application just schedules
execution of plugins. This chapter documents the built in plugins and how they are configured.
Note
The plugin execution order is determined by the plugins themselves using a fixed ordering value. The order of plugins in the configuration files does not make a difference.
etr.plugins.robot
¶
This is the plugin that enables the running of Robot Framework tests. It executes the specified tests and creates a merged report with detailed test results.
The etr.yaml
configuration is as follows:
version: "1.0"
plugins:
- etr.plugins.robot
robot:
mergedName: "top-level-suite"
tests:
- "src/my-test.robot"
- "src/my-other-test.robot"
Where the list under tests robot/tests
specifies the robot test files to be executed.
The attribute robot/mergedName
determines the top-level suite name for the merged report.
It is optional and by default the name of the directory containing the configuration file
(etr.yaml
) is used.
Note
etr
also makes available keyword libraries with utilities that can be used in the robot
tests. See Robot Framework Libraries for details.
etr.plugins.resources
¶
To acquire test resources automatically from a set of available the plugin
etr.plugins.resources
can be used.
Test resources can be anything and etr
does not use it directly. But attributes from acquired
resources can be used to process configuration files using the etr.plugins.jinja2
plugin for
example.
Resources can come from two sources:
Local configuration files where configuration file must be provided with
$RESOURCE_FILE
or--resource-file
option.Via the Resource Manager Web Service where the host must be provided with
$RESOURCE_HOST
or--resource-host
option.
Compared to the Resource Manager Web Service the local resources it does not provide any schema validation. So a specific resource type is not guaranteed to follow a specific schema.
To use local resources, create a file with the following structure:
version: "1.0"
resources:
<resource-id>:
type: <type>
tags:
- <tag>
- <tag>
attributes:
<attributes>
Where
<resource-id>
is the identifier for the resource in the file,
<type>
is the main resource type specifier.
<tag>
is an optional list of tags that can be used for filtering purposes by clients.
<attributes>
is the resource attributes that is added to the
etr
execution contexts so they can be used by e.g. other plugins.
An example configuration my-resources.yaml
of two opcua-shutter’s with some attributes.
Tags are optional and has been left empty in shutter2 in this example:
# my-resources.yaml
version: "1.0"
resources:
"lab-shutter-1":
type: "opcua-shutter"
tags:
- "v1"
attributes:
"server": "opc.tcp://134.171.12.186:4840"
"namespace": 4
"prefix": "MAIN.Shutter1"
"lab-shutter-2":
type: "opcua-shutter"
attributes:
"server": "opc.tcp://134.171.12.186:4840"
"namespace": 4
"prefix": "MAIN.Shutter2"
Note
The resource ids “lab-shutter-1” and “lab-shutter-2” are the identifiers for the resource
and can be anything in the character class [A-Za-z0-9_-]
. The resource IDs are only
used for the purpose of identifying locked resources and is not directly seen by the user
as the user defines their own name for the resource.
To acquire and use a resource the etr.yaml
is updated to include request the resource “shutter”
with type “opcua-shutter”:
version: "1.0"
plugins:
- etr.plugins.robot
- etr.plugins.resources
# Robot plugin configuration
robot:
tests:
- src/test.robot
# Resources plugin configuration
resources:
"shutter":
type: "opcua-shutter"
Note
The resource name “shutter” is the user provided name for the resource once it is acquired. This can be thought of as handle to the acquired resource attributes in e.g. the etr.plugins.jinja2 plugin.
etr.plugins.jinja2
¶
The etr.plugins.jinja2
plugin allows the processing of template files using the Jinja2 template
engine (c.f. the Jinja 2 documentation).
The etr.yaml configuration is simple and takes a dictionary or an array of dictionaries of files
to process as "input" -> "output"
files. An example that uses robot tests and Jinja2 follows:
New in version 3.0: Ability to order templates using array of objects.
version: "1.0"
plugins:
- etr.plugins.jinja2
- etr.plugins.robot
- etr.plugins.resources
# Resources plugin configuration which acquires the
# required resources
resources:
# My name/id for the acquired resource will be `shutter`.
"shutter":
type: "opcua-shutter"
# Jinja2 generates the src/test.robot file from the
# src/test.robot.j2 template file:
jinja2:
files:
"src/test.robot.j2": "src/test.robot"
# Robot finally runs the tests
robot:
tests:
- "src/test.robot"
To have a well-defined rendering order (first to last) the files can be specified as an array:
# ...
# Resources plugin configuration which acquires the
# required resources
resources:
# My name/id for the acquired resource will be `shutter`.
"shutter":
type: "opcua-shutter"
# Order is important so an array of files is used
jinja2:
files:
- "src/first.j2": "src/first"
- "src/second.j2": "src/second"
To acquire resources and run test using the resource file my-resources.yaml
above etr
is
invoked as:
etr --resource-file=my-resources.yaml
To make use of the attributes of the acquired resource we use the resource name shutter
as key
in the dictionary resources
which is made available in the Jinja2 environment.
Let’s imagine the acquired resource is the matching resource lab-shutter-2
. The specification
which includes the attributes we want to use from my-resources.yaml
is again (using example
from earlier):
# my-resources.yaml
# ... rest of file is omitted ...
"lab-shutter-2":
type: "opcua-shutter"
attributes:
"server": "opc.tcp://134.171.12.186:4840"
"namespace": 4
"prefix": "MAIN.Shutter2"
Then to access e.g. the server
attribute we use {{ resources.shutter.server }}
for
namespace
we use {{ resources.shutter.namespace }}
, and so on in the Jinja2 template.
Note
The name provided for a resource in the etr.yaml
configuration is the local name for the
resource which is used as the primary key to look up that resource in the “resources” dictionary
provided in the Jinja2 template.
The file src/test.robot.j2
might look like this:
*** Settings ***
Library Process
Library Shutter.py
*** Variable ***
${PLC_SERVER} {{ resources.shutter.server }}
${NAME_SPACE} {{ resources.shutter.namespace }}
${PREFIX_DEVICE1} {{ resources.shutter.prefix }}
${CMD_PORT} 5582
*** Test Cases ***
Reset PLC Controller
Reset Controller ${PLC_SERVER} ${NAME_SPACE} ${PREFIX_DEVICE1}
Sleep 2
When this is rendered by Jinja2 to the specified output file src/test.robot
, it contains all the
expanded variables from the acquired resource (notice how Jinja2 variables are expanded):
*** Settings ***
Library Process
Library Shutter.py
*** Variable ***
${PLC_SERVER} opc.tcp://134.171.12.186:4840
${NAME_SPACE} 4
${PREFIX_DEVICE1} MAIN.Shutter1
${CMD_PORT} 5582
*** Test Cases ***
Reset PLC Controller
Reset Controller ${PLC_SERVER} ${NAME_SPACE} ${PREFIX_DEVICE1}
Sleep 2
New in version 3.0: The ability to set and share variables across templates.
Using the do expr syntax in Jinja it is possible to set global variables that is accessible in the same and any other template that is rendered after the variable has been set (to make sure the templates are rendered in order you must use ordered files as described earlier):
{% do globals.update(variable="value") %}
{{ globals.variable }}
Where globals is the global dictionary variable provided by etr
.
etr.plugins.nomad
¶
The etr.plugins.nomad
plugin allows deployment using Nomad job specification files (c.f. the
Nomad documentation).
During setup each job specification file in nomad.jobs list is:
Registered (deployed) with Nomad (if the job already exists the registration will fail).
etr will monitor the job and wait for it to become stable (all tasks are running).
During teardown:
Each job will be unregistered (undeployed) in reverse order.
The etr.yaml configuration is simple and takes dictionary of job specification files register (deploy). An example that uses nomad follows:
version: "1.0"
plugins:
- etr.plugins.nomad
nomad:
jobs:
- "src/services.nomad"
Note
Currently support is limited to service job type.
Service discovery after deployment can be performed by using e.g. Consul.