chitamoor / Rester

Testing RESTful APIs
MIT License
85 stars 34 forks source link

Rester

Framework for testing (RESTful) HTTP APIs

Rester allows you to test your APIs using a non-programmatic or non-GUI based approach, which are some of the more conventional ways of testing RESTFul APIs. Rester is inspired by various unit testing frameworks like JUnit, 'unittest' (python) etc and is conceptually organized like those frameworks, but is geared towards testing RESTful API endpoints. With Rester, all tests are specified in YAML or JSON.

Why Rester?

Testing RESTful APIs generally involves two prediticable steps -

Most testing tools available for testing RESTful APIs use some sort of a GUI based approach which doesn't lend itself towards re-use, better code organization, abstraction and some of the other benefits that are generally available with more programmatic frameworks like JUnit. Programmatically building test cases provides the highest level of flexibility and sophistication, but the downside to this approach is that it ends up with lots of fairly tedious and repetitive code. Conceptually, Rester is similar to existing unit testing frameworks, but it uses JSON or YAML (instead of a programming language) to implement/specify the actual tests. Programmers and non-programmers can reap the benefits with the Rester approach.

Note: As of now Rester only supports APIs that don't require explicit authentication of calls, but future versions will support OAuth. Rester was mainly created to test internal APIs that generally bypass the need for authentication of the calls.

Practical uses of Rester

Assumptions

General Concepts

Globals can be defined in the either a TestSuite or TestCase.

globals:
  variables:
    request_opts: # special for the request library.
      verify: false # disable CERT checking for SSL
    http: "http://localhost:8905"
    https: "https://localhost:8081"
test_cases:
  - servers.yaml
  - cors.yaml
  - xdomain.yaml
  - notfound.yaml
name: "Ping"
globals: 
  variables: 
    http: "http://localhost:8905"
    https: "https://localhost:8081"
testSteps:
 - ...
 - ...

A TestStep contains the following:

URL is the only mandatory param.

Example of a TestStep (JSON):

  {
    "testSteps": [
        {
            "name":"Name of TestStep",
            "apiUrl":"http://example/api/v1/helloworld/print",
            "asserts":{
                "headers":{
                    "content-type":"application/json; charset=utf-8"
                },
                "payload":{
                    "message":"Hello World!"
                }
            }
        }
     ]
}

A complete example as YAML, leveraging the yaml references:

name: "Ping"
globals: 
  variables: 
    http: "http://localhost:8905"
    https: "https://localhost:8081"
testSteps: 
  - &test1
    name: "ping http"
    apiUrl: "{http}/ping"
    method: "get"
    raw: true
    asserts: 
      headers: 
        connection: "keep-alive"
        content-type: "text/plain; charset=utf-8"
      payload:
        __raw__: "pong"
  - 
    <<: *test1
    name: "ping https"
    apiUrl: "{https}/ping"

Example Output

See: https://gist.github.com/ninowalker/1fe8aad019feab3fe265

Installation

pip install git+https://github.com/chitamoor/Rester.git@master

Rester command line options

Other command line options

TestCase options

TestStep options

Examples of API request invocations

Examples of assert statements

As mentioned previously, all of the assert statements are specified within an asserts element

Assert specific payload elements

Assert logical operators:

  e.g. parent.child.message == "success"
      "payload":{
            "parent.child.message":"-eq success",  # either will work
            "parent.child.message":"success",
      }
  e.g. parent.child.message == "hello world"
      "payload":{
            "parent.child.message":"exec len(value) > 7 and value.endswith('world')",
      }

Storing intermediate values

Values from the payload can be extracted and assigned to variables in the variable name space. The assignments are specified as part of the postAsserts element and should be placed right after the asserts element.

    "asserts":{
        "headers": {
           ....
        },
        "payload":{
            "output.result":"Message Success",
            ....
        },
        ....
    },
    "postAsserts": {
        "variable_for_next_step":""output.id"
        ....
    }

Basic JSON Type checking

The following JSON types are supported - Integer, Float, String, Array, Boolean and Object

Support for lists/arrays

Using variables declarations

Dockerized Rester

Run the docker image raseev/rester

Running an existing test from the examples directory

  docker run -it --rm --name rester raseev/rester apirunner --ts examples/weather/test_suite.json 

  docker run -it --rm --name rester raseev/rester apirunner --ts examples/imdb/test_suite.json 

Running a new test

Use the docker volume option to specific the directory that contains the tests

  docker run -v $(pwd)/rester/examples:/tests -it --rm --name rester raseev/rester apirunner --ts tests/imdb/test_suite.json --log=DEBUG

Contact

rajeev@chitamoor.com

Contributors

Nino Walker - nino@livefyre.com

Changes

Unreleased

TODO