Skip to main content

HTTPX Client

vedro-httpx is a plugin designed for the Vedro testing framework. Its main goal is to simplify the process of sending HTTP requests via HTTPX, a fully-featured HTTP client that supports both synchronous and asynchronous APIs, as well as HTTP/1.1 and HTTP/2 protocols.

Setup

For a quick installation, you can use a plugin manager like so:

$ vedro plugin install vedro-httpx

Basics

The core functionality of the vedro-httpx plugin is provided by the AsyncHTTPInterface class. You can use this class to define your API interface. Below is an example of creating an AuthAPI interface for an authentication API:

from vedro_httpx import Response, AsyncHTTPInterface

class AuthAPI(AsyncHTTPInterface):
def __init__(self, base_url: str = "http://localhost") -> None:
super().__init__(base_url)

async def login(self, username: str, password: str) -> Response:
return await self._request("POST", "/auth/login", json={
"username": username,
"password": password
})

The _request() function is used to send HTTP requests. It passes the arguments directly to the httpx.AsyncClient.request() method.

tip

For a comprehensive understanding of the AsyncClient.request() method and its various parameters, see the official HTTPX documentation

Once you've defined your AuthAPI interface, you can incorporate it into your test scenarios. Here's an example scenario that simulates a registered user logging in:

import vedro
from contexts import registered_user
from interfaces import AuthAPI

class Scenario(vedro.Scenario):
subject = "login as registered user"

async def given_user(self):
self.user = await registered_user()

async def when_user_logs_in(self):
self.response = await AuthAPI().login(self.user["username"], self.user["password"])

def then_it_should_return_success_response(self):
assert self.response.status_code == 200

If scenario fails, vedro-httpx provides a beautifully formatted output of the response, including headers and the body:

$ vedro run -v
...


AssertionError: assert 201 == 200

Scope
user: {
"username": "ofo",
"password": "933ggv8hkhV_FLZ"
}
response: Response:
HTTP/1.1 201 Created
content-type: application/json; charset=utf-8
content-length: 98
date: Wed, 14 Jun 2023 11:16:41 GMT
server: Python/3.10 aiohttp/3.8.4
{
"username": "ofo",
"token": "d77cdd1765953fb9867796132a8330075e9521c0",
"created_at": 1686727001
}
note

This feature requires Vedro v1.9.1 or higher

Advanced Usage

In addition to the basic request method, the vedro-httpx plugin also allows you to directly use the HTTPX client.

from vedro_httpx import Response, AsyncHTTPInterface

class AuthAPI(AsyncHTTPInterface):
def __init__(self, base_url: str = "https://localhost") -> None:
super().__init__(base_url)

async def login(self, username: str, password: str) -> Response:
async with self._client(verify=False) as client:
return await self._request("POST", "/auth/login", json={
"username": username,
"password": password
})

This approach provides full flexibility in using the HTTPX AsyncClient directly, allowing you to control additional parameters such as SSL verification.

For more information and available parameters, check out the official HTTPX documentation.

Request Recording

The vedro-httpx plugin also enables recording of HTTP requests made during scenario execution and saving the data as a scenario artifact in HAR (HTTP Archive) format. This can be especially useful for debugging and auditing.

$ vedro run --httpx-record-requests

Artifacts, such as recorded HTTP requests, can be attached to an Allure report. Use the following command to generate an Allure report with HTTP request recordings:

$ vedro run -r rich allure --httpx-record-requests

If you prefer to save artifacts locally for offline analysis, you can use the --save-artifacts option. This will save the recorded HTTP requests as HAR files on your local file system:

$ vedro run --httpx-record-requests --save-artifacts

HAR files can be opened and analyzed using browser developer tools or local tools such as Fiddler or Insomnia. Additionally, you can use online tools like the Google HAR Analyzer for convenient, web-based viewing.

Generating OpenAPI Specs (beta)

The vedro-httpx plugin provides the ability to generate OpenAPI specifications from the HTTP requests recorded during test executions. This feature allows you to document your APIs dynamically based on real interactions.

info

Please note that the current implementation does not yet support the generation of request and response bodies.

  1. Record HTTP Requests During Test Execution:

    Start by running your test scenarios and recording the HTTP requests made during execution. Use the --httpx-record-requests and --save-artifacts flags to save these requests as HAR files:

    $ vedro run --httpx-record-requests --save-artifacts

    This command saves the recorded HTTP requests as HAR files in the .vedro/artifacts directory.

  2. Generate the OpenAPI Specification:

    Once the requests are recorded, you can generate the OpenAPI specification by running the following command:

    $ vedro_httpx .vedro/artifacts

    This command processes the saved HAR files and generates an OpenAPI spec based on them.

Important Considerations

When defining API routes with dynamic segments (e.g., user IDs), use the segments argument to avoid treating each request as a static path. Without it, the OpenAPI generator will interpret paths like /users/bob and /users/alice as separate static endpoints, leading to an inaccurate spec.

class AsyncAuthAPI(AsyncHTTPInterface):
async def get_user(self, username: str) -> Response:
return await self._request("GET", f"/users/{username}")
class AsyncAuthAPI(AsyncHTTPInterface):
async def get_user(self, username: str) -> Response:
return await self._request("GET", "/users/{username}", segments={
"username": username
})

This ensures the OpenAPI spec recognizes {username} as a dynamic parameter, resulting in a cleaner, more accurate path like /users/{username}.