REST API Testing Using Python

REST or RESTful API using JSON format has been very popular now because of its simplicity I believe. In this article, I am going to show you how to use Python to create a REST automation test suite using requests and flask packages.

Postman

First, I recommend you install and play with Postman. It allows you to create manual test scripts easily and also some level of automation (semi-automation) using variables and response assertion (Javascript only). The most important thing here is it can convert the manual scripts to sample codes in almost all languages including Python, so it is a good start point if you are new to API automation.

It is just 4 steps to create a Postman API request test:

  1. Select a request method
  2. Provide the API URL
  3. Add customized headers
  4. Add body

Then just click the Send button to send the request and check the response data.

And you can click the ‘Code’ button to convert the same request to a code snippet of your choice, e.g. Python in this case as shown below. Save the code into a python file, e.g. postman_code_snippet.py, and run it, and you will get the same response as you run the manual test in Postman.

Postman REST API example
Python code snippet from Postman

Build First Python REST API Test

To build a Python REST API test suite, you will need to install Python3 first, and below packages (using pytest test framework in this example).

pip install -U requests Flask pytest pytest-html

or install with pip3 if you have both Python2 and Python3 installed:

pip3 install -U requests Flask pytest pytest-html

Now let’s re-write the above code snippet in a simpler way and convert it to a pytest test as below.

Post API pytest example

As you can see, the Python script also just follows the steps as simple as Postman.

  1. Provide API URL
  2. Add customized headers
    Standard headers like Content-Length are taken care of by requests package.
  3. Add body
    Just create a dictionary variable for your request body, and convert it to json string format using json.dumps() function.
  4. Select a request method
    Use requests.post function for post request, and likewise requests.get for get request, etc.

Then we can simply validate the response by checking the response object resp. For example, resp.status_code for response status code, and resp.json() for response body content. Below is the response body print for this post request test, and to validate a field in the response body, e.g. “url”, we can just call assert resp.json()["url"] == "https://httpbin.org/post".

{
"args": {},
"data": "{\n \"key1\": 1,\n \"key2\": \"value2\"\n}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "39",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "Python Requests"
},
"json": {
"key1": 1,
"key2": "value2"
},
"origin": "103.115.210.48, 103.115.210.48",
"url": "https://httpbin.org/post"
}

Writing tests in Python is so easy and it gives the power of a programming language to support any flexibility needs, e.g. generate unique transaction id, read test data from a file, looping, or call another dependent API dynamically for an authentication token, etc.

Run with pytest

To run the test with pytest test framework, we need to define the function with test_ prefix and save the file with test_ prefix in the filename, e.g. test_post_headers_body_json.py. Then to run the test, just open a command prompt and type pytest in the script folder, and you will get a test result as follows.

pytest
================ test session starts =======================
platform win32 -- Python 3.7.3, pytest-4.4.1, py-1.8.0, pluggy-0.9.0
rootdir: D:\REST_API_Test_Framework_Python\Scripts\code_snippets
plugins: metadata-1.8.0, html-1.21.1
collected 1 item
test_post_headers_body_json.py . [100%]================= 1 passed in 1.61 seconds ====================

To get more details and generate a html report, run with below parameters. Check pytest --help for option details.

pytest -sv --html report.html

Logging

When something goes wrong, it is nice to a full snapshot of every request sent and response received, like the Postman console feature. So we add two pretty print functions as below to print every header, body and status code for request and response. And you can call them by pretty_print_request(resp.request) and pretty_print_response(resp).

Updated script with full logging of request and response
Logging example

Of course, you can write the logging to a file as well, e.g. using the standard logging module, as shown in the repository at the end.

Mocking with Flask

We use Python requests to send requests, and can use Flask to mock server endpoints. So you can perform TDD test development or validate your test code.

For example, below is the code to mock a service endpoint http://127.0.0.1:5000/json and return json format response
{“code”: 1, “message”: “Hello, World!” }.

Mock an HTTP service endpoint

Just save the code as a file, e.g. flask_mock_simple_service.py, and run it by python flask_mock_simple_service.py.

Then you can access this service by typing http://127.0.0.1:5000/json in a browser.

HTTP request from a browser

Or you can write a Python request test code as below.

Test mock service

Put It All Together

To put it together, you can download the full Python REST API test framework repository below, which includes everything mentioned above and more.

Appendix: Python vs JSON Format

Python dictionary looks very like JSON format, but there are still some differences, so you cannot simply put a quote around a dictionary to convert it to JSON string format, though it works most of the time, e.g. ‘{“key1”: “value1”}’ is a valid JSON string format.
Below is data mapping between Python and JSON format. Note that JSON format always uses double quotes for strings.

From https://docs.python.org/

Update

part 2: Scale-up REST API functional tests to performance tests in Python
part 3: Build Dynamic Rest API Mock Service

Code Simple | Python and AI Enthusiast @ Melbourne | peter.jp.xie@gmail.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store