Metadata-Version: 2.1
Name: RESTinstance
Version: 1.0.0rc3
Summary: Robot Framework test library for (RESTful) JSON APIs
Home-page: https://github.com/asyrjasalo/RESTinstance
Author: Anssi Syrjäsalo
Author-email: anssi.syrjasalo@gmail.com
License: Apache License 2.0
Keywords: robotframework test library testing rest http json api
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: POSIX
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Testing
Classifier: Framework :: Robot Framework
Classifier: Framework :: Robot Framework :: Library
Requires-Dist: robotframework (>=2.9)
Requires-Dist: flex (==6.13.2)
Requires-Dist: GenSON (==1.0.1)
Requires-Dist: jsonpath-ng (==1.4.3)
Requires-Dist: pygments (==2.2.0)
Requires-Dist: requests (==2.20.0)
Requires-Dist: jsonschema (==3.0.0a3)
Requires-Dist: rfc3987 (==1.3.8)
Requires-Dist: strict-rfc3339 (==0.7)
Requires-Dist: pytz (==2018.5)
Requires-Dist: tzlocal (==1.5.1)

RESTinstance
============

`Robot Framework <http://robotframework.org>`__ test library for (RESTful) JSON APIs


Advantages
----------

1. **RESTinstance relies on Robot Framework's language-agnostic,
   clean and minimal syntax, for API tests.** It is neither tied to any
   particular programming language nor development framework.
   Using RESTinstance requires little, if any, programming knowledge.
   It builts on long-term technologies with well established communities,
   such as HTTP, JSON (Schema), Swagger/OpenAPI and Robot Framework.

2. **It validates JSON using JSON Schema, guiding you to write API tests
   to base on properties** rather than on specific values (e.g. "email
   must be valid" vs "email is foo\@bar.com"). This approach reduces test
   maintenance when the values responded by the API are prone to change.
   Although values are not required, you can still test them whenever they
   make sense (e.g. GET response body from one endpoint, then POST some
   of its values to another endpoint and verify the results).

3. **It generates JSON Schema for requests and responses automatically,
   and the schema gets more accurate by your tests.**
   Output the schema to a file and reuse it as expectations to test the other methods, as most of them respond similarly with only minor differences.
   Or extend the schema further to a full Swagger spec (version 2.0,
   OpenAPI 3.0 also planned), which RESTinstance can test requests and
   responses against. All this leads to reusability, getting great test
   coverage with minimum number of keystrokes and very clean tests.


Installation
------------

Three installation methods are supported. Pick the one that suits you best.

As a Python package
~~~~~~~~~~~~~~~~~~~
On 3.x and 2.7, you can install or upgrade `from PyPi <https://pypi.org/project/RESTinstance>`__:

::

    pip install --upgrade RESTinstance

As a Docker image
~~~~~~~~~~~~~~~~~

`The RESTinstance Docker image <https://hub.docker.com/r/asyrjasalo/restinstance/tags>`__ contains Python 3.6 and `the latest Robot Framework <https://pypi.org/project/robotframework/3.0.4>`__:

::

    cd <path_where_your_tests_are>

::

    docker pull asyrjasalo/restinstance
    docker run --rm -ti --env HOST_UID=$(id -u) --env HOST_GID=$(id -g) \
      --env HTTP_PROXY --env HTTPS_PROXY --network host \
      --volume "$PWD/tests":/home/robot/tests \
      --volume "$PWD/results":/home/robot/results \
      asyrjasalo/restinstance tests

Using rfdocker
~~~~~~~~~~~~~~
If already using `rfdocker <https://github.com/asyrjasalo/rfdocker>`__,
add ``RESTinstance`` to ``requirements.txt`` and uncomment the lines
in ``Dockerfile``.  It is installed next time ``./rfdocker`` is ran.

To pass the proxy settings to the container and run it on the host network:

::

    RUN_ARGS="--env HTTP_PROXY,HTTPS_PROXY --network=host" ./rfdocker


Usage
-----

There is a `step-by-step tutorial <https://github.com/asyrjasalo/RESTinstance/blob/master/examples>`__
in the making, best accompanied with the  `keyword documentation <https://asyrjasalo.github.io/RESTinstance>`__.

Quick start
~~~~~~~~~~~

Tip: Run this ``README.rst`` as a test suite with Robot Framework.

.. code:: robotframework

    *** Settings ***
    Library         REST    https://jsonplaceholder.typicode.com
    Documentation   Test data can be read from variables and files.
    ...             Both JSON and Python type systems are supported for inputs.
    ...             Every request creates a so-called instance. Can be `Output`.
    ...             Most keywords are effective only for the last instance.
    ...             Initial schemas are autogenerated for request and response.
    ...             You can make them more detailed by using assertion keywords.
    ...             The assertion keywords correspond to the JSON types.
    ...             They take in either path to the property or a JSONPath query.
    ...             Using (enum) values in tests optional. Only type is required.
    ...             All the JSON Schema validation keywords are also supported.
    ...             Thus, there is no need to write any own validation logic.
    ...             Not a long path from schemas to full Swagger/OpenAPI specs.
    ...             The persistence of the created instances is the test suite.
    ...             Use keyword `Rest instances` to output the created instances.


    *** Variables ***
    ${json}         { "id": 11, "name": "Gil Alexander" }
    &{dict}         name=Julie Langford


    *** Test Cases ***
    GET an existing user, notice how the schema gets more accurate
        GET         /users/1                  # this creates a new instance
        Output      schema response body
        Object      response body             # values are fully optional
        Integer     response body id          1
        String      response body name        Leanne Graham
        [Teardown]  Output                    # note the updated response schema

    GET existing users, use JSONPath for very short but powerful queries
        GET         /users?_limit=5           # further assertions are to this
        Array       response body
        Integer     $[0].id                   1           # first id is 1
        String      $[0]..lat                 -37.3159    # any matching child
        Integer     $..id                     maximum=5   # multiple matches
        [Teardown]  Output  $[*].email        # outputs all emails as an array

    POST with valid params to create a new user, can be output to a file
        POST        /users                    ${json}
        Integer     response status           201
        [Teardown]  Output  response body     ${OUTPUTDIR}/new_user.demo.json

    PUT with valid params to update the existing user, values matter here
        PUT         /users/2                  { "isCoding": true }
        Boolean     response body isCoding    true
        PUT         /users/2                  { "sleep": null }
        Null        response body sleep
        PUT         /users/2                  { "pockets": "", "money": 0.02 }
        String      response body pockets     ${EMPTY}
        Number      response body money       0.02
        Missing     response body moving      # fails if property moving exists

    PATCH with valid params, reusing response properties as a new payload
        &{res}=     GET   /users/3
        String      $.name                    Clementine Bauch
        PATCH       /users/4                  { "name": "${res.body['name']}" }
        String      $.name                    Clementine Bauch
        PATCH       /users/5                  ${dict}
        String      $.name                    ${dict.name}

    DELETE the existing successfully, save the history of all requests
        DELETE      /users/6                  # status can be any of the below
        Integer     response status           200    202     204
        Rest instances  ${OUTPUTDIR}/all.demo.json  # all the instances so far


Development
-----------

Bug reports and feature requests are tracked in
`GitHub <https://github.com/asyrjasalo/RESTinstance/issues>`__.

We do respect pull request(er)s. Please mention if you do not want to be
listed below as contributors.

Library's own tests
~~~~~~~~~~~~~~~~~~~

For simplicity, `Docker <https://docs.docker.com/install>`__ is required for running `the library's own tests <https://github.com/asyrjasalo/RESTinstance/tree/master/tests>`__. No other requirements are needed.

To spin up the environment and run the tests:

::

    scripts/test

To run them on Python 2.7:

::

    BUILD_ARGS="-f Dockerfile.python2" BUILD_NAME="restinstance-python2" scripts/test

System under test
~~~~~~~~~~~~~~~~~

The test API is implemented by
`mounterest <https://github.com/asyrjasalo/mounterest>`__, which in turn
bases on `mountebank <https://www.mbtest.org>`__.

In the scope of library's tests, mounterest acts as a HTTP proxy to
`Typicode's live JSON server <https://jsonplaceholder.typicode.com>`__ and uses
mountebank's injections to enrich responses slightly, so that they
better match to this library's testing needs. Particularly, it allows
to test the library with non-safe HTTP methods (POST, PUT, PATCH,
DELETE) by mimicking their changes, instead of trying
to issue them on the live server. The changes are cleared between the test
runs.

Releasing
~~~~~~~~~

To update `keyword documentation <https://asyrjasalo.github.io/RESTinstance>`__:

::

    scripts/genlibdoc


To create a new ``.venv``, build a Python package and upload it PyPi:

::

    scripts/release_pypi

To build a Docker image with ``/src``, tag it and push it to Docker registry:

::

    scripts/release_docker https://your.private.registry.com/restinstance

To do the same for Docker Hub you can use:

::

    scripts/release_docker {{organization}}/restinstance


Credits
-------

RESTinstance is licensed under `Apache License 2.0 <https://github.com/asyrjasalo/RESTinstance/blob/master/LICENSE>`__ and was originally written by
`Anssi Syrjäsalo <https://github.com/asyrjasalo>`__.

It was presented at (the first) `RoboCon 2018 <https://robocon.io>`__.


Contributors:

- `jjwong <https://github.com/jjwong>`__
  for helping with keyword documentation and examples (also check
  `RESTinstance_starter_project <https://github.com/jjwong/RESTinstance_starter_project>`__)

- `Przemysław "sqilz" Hendel <https://github.com/sqilz>`__
  for using and testing RESTinstance in early phase (also check
  `RESTinstance-wrapper <https://github.com/sqilz/RESTinstance-wrapper>`__)


We use the following Python excellence under the hood:

-  `Flex <https://github.com/pipermerriam/flex>`__, by Piper Merriam,
   for Swagger 2.0 validation
-  `GenSON <https://github.com/wolverdude/GenSON>`__, by Jon
   "wolverdude" Wolverton, for JSON Schema generator
-  `jsonpath-ng <https://github.com/h2non/jsonpath-ng>`__,
   by Tomas Aparicio and Kenneth Knowles, for handling JSONPath queries
-  `jsonschema <https://github.com/Julian/jsonschema>`__, by Julian
   Berman, for JSON Schema validator
-  `pygments <http://pygments.org>`__, by Georg Brandl et al.,
   for JSON syntax coloring, in terminal `Output`
-  `requests <https://github.com/requests/requests>`__, by Kenneth
   Reitz et al., for making HTTP requests

See `requirements.txt <https://github.com/asyrjasalo/RESTinstance/blob/master/requirements.txt>`__ for all the direct dependencies.


