Declaritive REST API Testing framework
npm install teakozi 
Teakozi is a declarative REST API testing framework for testing micro-services. Here are the capabilities.
- Writing tests as readable YML files
- Externalize the configuration / environment specific parameters
- Dynamic Data - Collect Property and use it in subsequent steps.
- Scenario based testing. Externalize the test data and validation data from test specification
- Reuse API calls in multiple tests
- Validate response schema as per Swagger definitions
- Library extensions
- include teakozi in your node application
``sh`
$ npm install teakozi
create a directory in your project consisting of the following subdirectories
- tests
- tests/[testname].yml
- modules
- modules/[modulename].yml
- models
- models/[modelxx].js
- config
- config/index.js
- payload
- payload/[xxx].json
| Directory | Purpose|
|-|-|
|tests|contains the yml files that describe the tests. You can arrange the test yml files in any suitable folder hiererchy. the framework will get all yml files in directory under this tree and ignore all the non .yml files|
|modules|reusable test steps that can be refered in the test yml file|
|models|externalize the data to drive the tests|
|config|just one index.js file |
|payload|the body of the content that can be called in a post step. This folder also contains the json payload against which you need to validate your responses. |
see the example folder in the repo for reference. you need to update the config/index.js with your github auth to
sync tag can be applied at the config level and also at file level. the framework will execute the test in the following manner
|SYNC|Config true|Config false|Config undefined|
| - | - |-|-|
|Test - true|Sync|Sync|Sync|
|Test- false|Sync|Async|Async|
|Test - undefined|Sync|Async|Sync|
This behavior is subject to change based on user feeback. Current phillosophy - default to sync when not explicit
``
module.exports = {
swagger:'/config/swagger.yml',
lib:{
increment : function(i){return ++i},
decrement : function(i){return --i}
}
};
you can now use the increment and decrement functions while collecting the parameters from response. example
`
collect:
incremeted_id: increment->$.order[0].id
print:
- $.order[0].id
- incremeted_id
`
in a .js file call
``
require("teakozi").start("project/example")
| Property |required| type | Purpose|
| - | - |-|-|
|name|required|string|Name of the Test Case |
|tags|optional|string|comma saperated list of tags for the test. you can use thse tags to filter / select the test you would like to take for a test run |
|sync|optional|bool|Whether the test should run sync / async. please refer to section sync / async as the behavior is dependent on this and config sync flag |
|iterate|optional|string|Name of the module file that returns an array of objects. The test steps defined will be repeated for all the elements of this array |
|steps|required|array|See Steps Section|
example:
`sh`
post:
url: "https://api.github.com/gists/~gist_id~/comments"
json: "create_comment.json"
override:
$.body: ~comment_text~
headers:
Authorization: Basic xxxx
content-type: application/json
User-Agent: Teakozi-test
Example:
`sh`
local:
file: roads
Example:
`sh`
- mongo:
server: "mongodb://localhost:27017"
db: 'test'
collection: "test"
query:
name: j
sh
collect:
title: $..[0].name
project_id: $..[0].id
`collect also supports reading complete or subset of json recieved like
`sh
collect:
all_roads: $..Name
`this will collect all the Name fields comming at any part of the json. using JSON path expression on the right hand side you can collect specific sections of json for comparision
$3
Enables debugging of the call by printing the jsonpaths from the response`sh
- get:
url: "http://localhost:3060/k.json"
name: "Get Auth K"
print:
- status
- $.mykey
check:
status: 200
collect:
auth_key: $.mykey
`print also supports checking the objects / subset of json as defined by json path like
print:
- status # status of the header
- $..Name # All names appearing in the json
- $[0].Name # Prints name value of the first record
- $ # Prints complete JSON
$3
| Property |required| type | Purpose|
| - | - |-|-|
|status|optional|number|what status code is expected in response |
|schema|optional|string|you can add the name of the Model corresponding to the expected response. The swagger definition should be done in config/index.js |
|eq|optional|object|the jsonpaths that should be equal to |
|neq|optional|object|the jsonpaths that should notbe equal to |
|null|optional|array|the jsonpaths that should be null |
|deepEqual| optional|array| The jsonpaths and what collected objects to check against.
|shallowEqual| optional|array| compare two collected json to match and validate such that each element of A is present in the B (A is a subset B is a superset)
|regex| optional|array| The jsonpaths and their matching regex. The regex expression can be external mentioned as ~regex_for_currency~ or mentioned inlineexample:
`sh
check:
status: 200
schema: Domain
body:
eq:
$.length: 20
$..[0].name: "devops_best_practices"
regex:
$.domain: "^Ji[a-z]*"
neq:
$.length: 0
null:
- $.nonexistant
- $.someother_nonexistant
deepEqual:
$: full_roads_payload
$..Name: all_roads
shallowEqual:
- sub: sub
super: super
ar: empid
permissionList: permissionId
`
where full_roads_payload is collected in a previous step
The check expression can be json path expression or can also represent a collected value from a previous or current step
$3
Shallow Equal is a way to compare two collected jsons to match and validate such that each element of A is present in the B (A is a subset B is a superset).
| Property |required| type | Purpose|
| - | - |-|-|
|sub|required|string|the name of the object collected in this or previous steps that should be the subset |
|super|required|string|the name of the object collected in this or previous steps that should be the superset |
|[key]|optional / multi|string| key is the arrays in the object and value is the attribute of the object that should be used to compare and identify the object |
example
JSON A (subset)
`sh
{
organization:"abc",
address:"outer ring road",
city:"bangalore",
employees:[{
emp: 123,
name: "Ned Stark"
},{
emp: 234,
name: "John Snow"
}]
}
`JSON B (superset)
`sh
{
organization:"abc",
address:"outer ring road",
city:"bangalore",
pin: 560102
employees:[{
emp: 123,
name: "Ned Stark",
cool: true
},{
emp: 234,
name: "John Snow"
},{
emp: 345,
name: "Sansa"
}]
}
`
if test.yml shallowEqual:
- sub: A
super: B
employees: empid
Result: Pass
$3
Save is a utility that allows the resoponse recieved from the step into a file. you have control to save the full payload or partial payload using jsonpath
example:
`sh
save:
$: "file_mongo_recs"
$..name: "names_in_response"
`$3
Define the location of the swagger file in your config/index.js with the name
`sh
swagger: /config/swagger.yaml
`
In your check attribute you can add the name of the Model corresponding to the expected response.
`sh
check:
schema: Domain
`
The framework will add an assertion step to check if the schema of the response is matching with the schema as defined in the swagger. the assertion fails if the schema is not found or schema mismatch. the details of which all attribute are not matching schema is described in the test log JSON and viewable in the teakozi-viewer.Running a subset of your test suits based on tags
in your index.js file
`sh
var tags_list = "a,b,c,d"
require("teakozi").start("project/github",working dir,{tag:tags_list})
`
run the test cases
`sh
$ node index.js
`Chaining test execution
The start function returns a promise that is resolved when tests complete. you can chain further tests like following or handle the test end event for any other handling
`
var dir = "/home/jitendra/code/teakozi-examples"
var t = require("teakozi")
t.start("project/github",dir,{tag:"cars"})
.then(()=>{
t.start("project/github",dir,{tag:"swagger"})
})
``The test logs are shown on screen and the logs are written into the project directory/log with a timestamped folder containing all and individual test run information