OpenTestingAPI

Version 1.5

Application Testing for Everyone

Version 1.4

OpenTestAPI Specification

[Download JSON Schema Specification 1.4]

Disclaimer

Part of this content has been taken from the great work done by the folks at the [AsyncAPI] initiative and the [OpenAPI] initiative.

Introduction

The OpenTestAPI specification is a project to describe and document tests cases in a machine-(and human-)readable format. The specification defines a set of files to describe a test case. Creation and execution of the test cases can be done by utilities.

Schema Specification

OpenTestAPI Object

This is the root document object for the API specification. It combines resource listing and API declaration together into one document.

FIELD NAMETYPEDESCRIPTION
testapiVersion StringRequired Specifies the TestAPI version. Can be used by clients to interpret the version.
idIdentifierIdentifier of the test case, which will be delivered.
descriptionStringThe informal description of the test case.
injections[Injection Object]The set of injection objects, part of this testcase.
checks[Check Object]The set of check objects, part of this testcase.
labelsString Arraylabels applied to the test case, used for additional features like search

TestAPI Version String

The version string signifies the version of the TestAPI Specification that the document complies to. The format for this string must be major.minor.

A major.minor shall be used to designate the TestAPI Specification version, and will be considered compatible with the TestAPI Specification specified by that major.minor version.

In subsequent versions of the TestAPI Specification, care will be given such that increments of the minor version should not interfere with operations of tooling developed to a lower minor version. Thus a hypothetical 1.2 specification should be usable with tooling designed for 1.0 (clean handling of allowed values required as minor versions might increase allowed value ranges and add new optional values).

Identifier

This field represents a unique universal identifier. The format is in general free, but it can be used to package test cases to testsuites. Good practice is to follow the URI format, according to RFC3986.

EXAMPLE

{
    "id": "myproject:myexampleapplication:E2E:test1" 
}
{
    "id": "myproject:myexampleapplication:E2E:test1:kafka:inject:mymessage" 
}

Injection Object

FIELD NAMETYPEDESCRIPTION
injectidIdentifierRequired A unique Identifier, which allows to connect an inject with several checks.
descriptionStringThe informal description of the test case inject.
serviceService ObjectRequired the service (interfaces), which will be used to inject the testing data.
checks[Checks]A set of checkids, describing the checks executed after the inject was triggered.
injections[Injection Object]The set of sub injection IDs. (API 1.4)
cron[Cron Trigger]The execution time of a job. (not required for pipeline or API/manual execution)
executionsIntegerThe amount of execution (default: 1), can be used for load scenarios or counting based on pre-existing random data in pool. (API 1.3)
timetoliveTime Duration ObjectBased on the continuous execution approach, a test case will be executed endless. timtolive defines how long the test cases has to be executed by the test tool once it was started. If nothing is defined, the assumption will be that the test cases is executed endless based on the cron job.
sourcefileFilenameThe data source for the inject. The complete data of this file will be taken ans input for the SUT.
replacementReplacement ObjectIt’s possible to inject random generated data into the input object. If the testing tool supports the feature, it is also possible to trace the random generated values through the test case. That is, once a random value was generated, it can be used inside the output check for validation.

Service Object

A SUT can have several interfaces for interaction. The OpenTestAPI defines a common approach to interact with different service interfaces. Therefore, OpenTestingAPI defines a common and a custom configuration part. The custom configuration

The common service configuration part looks as follows

FIELD NAMETYPEDESCRIPTION
typeStringRequired The definition of the service type.
connectstringStringRequired The connect string for the service. Usually, this will be an Url. However, its also possible to interact via other interfaces, e.g. files.
userStringIn case of authentication, the username.
passwordBase64StringThe password for the authentication.
custom[(String, String)]A service can have custom configurations, e.g. topics etc. The custom list allows the simple configuration via key/value pairs.

At this moment, the OpenTestAPI supports the following services:

ServiceType-StringDESCRIPTION
KafkakafkaApache Kafka is an often used technology for asynchronous communication and data stream processing. The SUT communicates via topics with its environments.
JDBC DatabasejdbcConnect to JDBC Databases, e.g. PostgreSQL, MariaDB, Oracle DB
Cassandra DatabasecassandraConnect to Cassandra Database
RESTrestConnect a service via HTTP Requests.
S3s3Connect a S3.

ATTENTION: Do NOT use any technologies effecting business process, for example queues!

Kafka Service Object

Addition / Custom Fields:

FIELD NAMETYPEDESCRIPTION
topicStringRequired The topic to inject data / consumer data from.
group.idStringKafka uses consumer groups to cooperate consumers of one topic. The SUT and the testing tool will consume data from the same topic. For this, a dedicated testing group is required.
security.protocolStringrequired when using user and password
sasl.mechanismStringrequired when using user and password
login.moduleStringrequired when using user and password

EXAMPLE

{
    "service": {
        "type": "kafka",
        "connectstring":"mykafkabroker.com",
        "username": "",
        "password": "",        
        "custom": [
            {
                "key": "topic",
                "value": "mytopic"
            },
            {
                "key": "group.id",
                "value": "mygroup"
            }
        ]             
    }
}

JDBC Service Object

The connectstring for SQL databases follows the JDBC Url syntax. The Url string consists of a protocol-, host-, database- and properties definition.

EXAMPLE

{
  "service": {
        "type": "jdbc",
        "connectstring":"jdbc:oracle:thin:@localhost:1521/XE",
        "username": "myusername",
        "password": "dW5zZWN1cmUgcGFzc3dvcmQ="    
    }
}

Cassandra Service Object

Please use server:port to specify the target cluster.

EXAMPLE

{
  "service": {
        "type": "cassandra",
        "connectstring":"cassandra-db:9042",
        "username": "myusername",
        "password": "dW5zZWN1cmUgcGFzc3dvcmQ="    
    }
}

REST Service Object

Addition / Custom Fields:

FIELD NAMETYPEDESCRIPTION
typeStringHTTP-method, which has to be performed, e.g. GET, POST (see rfc7231).

EXAMPLE

{
  "service": {
        "type": "rest",
        "connectstring":"http://localhost:50000/dummy/post",
        "username": "myusername",
        "password": "dW5zZWN1cmUgcGFzc3dvcmQ=",
        "custom": [
            {
                "key": "type",
                "value": "post"
            }
        ]   
  }
}

S3 Service Object

Addition / Custom Fields:

FIELD NAMETYPEDESCRIPTION
regionStringS3 region
bucketNameStringBucket name
fileNameStringFilename

EXAMPLE

{
  "service": {
        "type": "s3",
        "connectstring":"s3-serviceEndpoint",
        "username": "myaccesskey",
        "password": "mysecretaccesskey",
        "custom": [
            {
                "key": "type",
                "value": "post"
            }
        ]   
  }
}

Check Object

FIELD NAMETYPEDESCRIPTION
checkidIdentifierRequired A unique ID for the check.
descriptionStringThe informal description of the test case check.
serviceServicesRequired the service (interfaces), which will be used to check the testing data.
validations[Validation Object]Required the validation, which define the check
maxwaitimeTime Duration ObjectRequired This defines the maximum time a testing tools has to wait before it marks a check as failed. If the expected output arrives in the timeframe (inject-start, maxwaitime) the test will be reported as success.
intervallTime Duration ObjectThis defines the time intervall between check executions, default is 10s.
activeStringactivate (TRUE, default) /deactivate (FALSE) a check. Per default a testing tool will set a check always as activated and execute it once, the inject referenced it.
mandatoryStringmandatory (TRUE, default) /optional (FALSE) check. Chained checks and injects are stopped if a mandatory check fails, for optional ones it will continue.
checks[Checks]A set of checkids, describing the checks executed after the check was successful (or non-mandatory and failed).
injects[Checks]A set of injectids, describing the injects executed after the check was successful (or non-mandatory and failed).

Validation Object

FIELD NAMETYPEDESCRIPTION
orderNumberA JSON List object has per default no order. In order to sort the sub value generation an order ID is introduced. This parameter is optional.
requestFilenameThe file contains the request object (inside a file), which has to be executed on the inject interface. In case of a SQL DB System its an SQL query.
response[Filename]Required The data source for the expected response object.
typeStringRequired Check type defines, how to perform the output validation. Valid values are EQUALS, CONTAINS, CONTAINSNOT, CONTAINSONEOF… . See Check Type Definition

EXAMPLE

{
  "validations" : [{
        "order": 1,
        "request": "check_postgresql_param_1.sql",
        "type": "containsOneOf",
        "response": [ "expected_result_test1.txt", "expected_result_test2.txt"]        
      }
  ]
}

Checks

A set of checkids, describing the checks executed after the inject was triggered.

EXAMPLE

{
    "checks": [ "kafka:check1", "kafka:check2", "oracle:check1"]
}

Check Type Definition

The Open-Test-API supports the following types of validation:

CHECKDESCRIPTION
equalsThe testing tool reports success if the output is equal to the expected output.
containsThe testing tool reports success if all output files contain valid output.
containsnotThe testing tool reports success if the output does not contain the expected output.
containsoneofThe testing tool reports success if one of the response files contains the expected output.
regexThe testing tool reports success if the output matches the expected regex. (API v1.1)
jsonschemaThe testing tool reports success if the output matches the expected JSON schemata. (API v1.1)

Hint regex: You might want to use an Online tool first to escape your content before adding real regex, otherwise you will fail with special characters.

Cron Trigger

The Cron Trigger is a comma-separated list of cron jobs. The cron job definition follows the UNIX cronjob definition ([Cron Job])

The following examples will trigger the data inject every hour 5 and 15 minutes after the full hour.

EXAMPLE

{
    "cron" : [ "5 * * * * ?" , "15 * * * * ?"], 
}

Filename

The text content of file will be taken as the input for injects and/or checks. The filename can be name only or relative path to your data source. It’s a good practice to have the files next to your testcase description, e.g. all data sourcefiles for a testcase are inside a directory together with the testcase.
Within test case definition you MUST use the filename only, as implementation is not aware of storage type and folders - upload will use filename only!

EXAMPLE With relative path ./

/testcase1/testcasedescription.json
/testcase1/inject1.txt
/testcase1/inject2.txt
/testcase1/check1.txt
/testcase1/check2.txt

or with relative path testcase1/

testcasedescription.json
/testcase1/inject1.txt
/testcase1/inject2.txt
/testcase1/check1.txt
/testcase1/check2.txt

Time Duration Object

A time duration MUST be a number bigger 0 representing the duration in seconds. For simplification, the following abbreviations are possible:

AbbreviationsDescription
sseconds
mminutes
hhours
ddays

EXAMPLE

{
  "maxwaitime": "60",
  "maxwaitime": "60s",
  "maxwaitime": "1m",
}

Replacement Object

It’s possible to inject random generated data into the input object and validate the output object for this generated date.

With this, it’s possible to trace objects during a complex SUT overall several subsystems.

A replacement object is a set of

FIELD NAMETYPEDESCRIPTION
replacements[Replacement Rule]A set of replacements.

Replacement Rule

FIELD NAMETYPEDESCRIPTION
keyStringThe key defining the replacement object. The testing tool will look for this key to replace it by the random generated value.
value[Replacement Value]A comma separated list of values for the replacement, the concatenation of this list will be the replacement value.
maxlengthInteger

Replacement value

The description of a single value looks as follows

FIELD NAMETYPEDESCRIPTION
orderNumberA JSON List object has per default no order. In order to sort the sub value generation an order ID is introduced. This parameter is optional.
typeStringDefines the way how to generate random values. Type and its parameters are described in the next table.
valueStringDefines the specific definition how to generate random values.
paramStringParameter object for the random generator.

The following types are supported by the OpenTestApi Definition

FIELD NAMETYPEDESCRIPTION
nowStringValue will be the current timestamp (+an additional delay) in the given format. Parameter (param) accepts (+delay)
listStringList of Pipe ("|") separated values, which can be picked randomly for the value. The values are grabbed evenly distributed.
regexStringRandom generated value matching the regular expression
inheritfromStringInherit from different Inject (InjectID as value) with same #key#
fileFilenameThe file contains a set of values, which are randomly chosen. One value per line.

EXAMPLES

A simple timestamp example:

"replacements" : [
{
    "key" : "#key1#",
    "value": [{   
        "order": 1,
        "type": "now",    
        "value": "yyyy-MM-dd HH:mm:ss",
        "param" : "+1h"
    }]   
}]

This will generate a replacement value, which generates a timestamp with one hour in the future. That is, your inject job will be done at 10am, the generated value will be 11am.

"replacements" : [
{
    "key" : "#key1#",
    "value": [{        
        "order": 1,
        "type": "list",    
        "value": "v1|v2|v3|v5"
    }]   
}]

The generator will pick random one of the values out of the list given as param.

"replacements" : [
{
    "key" : "#key1#",
    "value": [{        
        "order": 1,
        "type": "regex",    
        "value": "^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$"
    }],        
}]

This regex generates a UUID in format v4.

A more complex example combines several generators:

"replacements" : [
{
    "key" : "#key1#",
    "value": [{
        "order": 1,
        "type": "list",    
        "value": "v1_0|v2_|v3_|v5_00"
    },{
        "order": 2,
        "type": "regex",    
        "value": "^[0-9]{2}$"
    }],
    "maxlength":5
}]

This will pick a value out of the list “v1_0, v2_, v3_, v5_00” and append a random value between 0 and 99. The result will be cut at length 5, you will end up having only minor version 00 for v5 and minor version 00 to 09 for v1.

YML support (optional)

For readability, we recommend supporting the YML format. However, conversion can also be done as an upstream step, so this feature is optional.

Last updated on 9 Aug 2023
Published on 9 Aug 2023
 Edit on GitHub