Getting Started with HTTPX, Part 4: pytest-asyncio and pytest_httpx (Asynchronous Version)
Tags: python, pytest, asyncio, httpx
Published: 2020-08-13 15:34:21

In [Part 2], we explored how to write tests and mocks using [pytest] and [pytest_httpx] for the synchronous version of the client, which was built in [Part 1].

Now that we have the asynchronous version from [Part 3], let's write asynchronous tests.

## Install latest [pytest], [pytest-asyncio], and [pytest_httpx]

In order to test asynchronous functions, we first need a suitable asyncio pytest plugin. Let's add [pytest-asyncio] as a development dependency, and also make sure [pytest] and [pytest_httpx] are installed:

```bash
poetry add -D pytest@latest pytest_httpx pytest-asyncio
```

If you already upgraded [pytest] and installed [pytest_httpx], then just `poetry add -D pytest-asyncio` will do.

## Add an asynchronous test

Let's revise our test module, keeping the synchronous bits, and adding an asynchronous test:

```python
import pytest

import pypedia.asynchronous
import pypedia.synchronous

ARTICLES = {
    "pages": [
        {
            "id": 23862,
            "key": "Python_(programming_language)",
            "title": "Python (programming language)",
            "excerpt": "Python is an interpreted, high-level, general-purpose programming language.",
            "description": "An interpreted, high-level, general-purpose programming language.",
        },
        {
            "id": 226402,
            "key": "Guido_van_Rossum",
            "title": "Guido van Rossum",
            "excerpt": "Guido van Rossum; the creator of the Python programming language",
            "description": "Dutch programmer and creator of Python",
        },
    ]
}
SEARCH = "incategory:Python_(programming_language)"
URL = "https://en.wikipedia.org/w/rest.php/v1/search/page?q=incategory%3APython_%28programming_language%29&limit=100"


def test_mock_sync_search(httpx_mock):
    httpx_mock.add_response(url=URL, json=ARTICLES)
    response = pypedia.synchronous.search(SEARCH)
    assert response.status_code == 200
    assert "Guido" in response.text


@pytest.mark.asyncio
async def test_mock_async_search(httpx_mock):
    httpx_mock.add_response(url=URL, json=ARTICLES)
    response = await pypedia.asynchronous.search(SEARCH)
    assert response.status_code == 200
    assert "Guido" in response.text
```

There is not a whole lot of difference between the synchronous and the asynchronous versions of the tests, thanks to [pytest_httpx].

- We need to `import pytest` so that the `@pytest.mark.asyncio` decorator can be used.
- Use the `@pytest.mark.asyncio` decorator on the async test function.
- The tests need to be awaitable. In other words, use the `async` keyword before the function definition.
- Use the `await` keyword before calling the asynchronous function(s) we built.

## Run the tests

Do the tests succeed?

```bash
poetry run pytest
```

Asynchronous bliss.

I hope this introductory exploration of [HTTPX] is useful for you as a launchpad for more robust API client projects. Happy developing.

[pytest-asyncio]: https://pypi.org/project/pytest-asyncio/
[event loop]: https://docs.python.org/3/library/asyncio-eventloop.html
[gather]: https://docs.python.org/3/library/asyncio-task.html#asyncio.gather
[pytest]: https://docs.pytest.org/
[Python]: https://www.python.org/
[Part 1]: https://dev.to/bowmanjd/getting-started-with-httpx-building-a-python-rest-client-234n
[Part 2]: https://dev.to/bowmanjd/getting-started-with-httpx-part-2-pytest-and-pytesthttpx-2jef
[Part 3]: https://dev.to/bowmanjd/getting-started-with-httpx-part-3-building-a-python-rest-client-asynchronous-version-3lb0
[Part 4]: https://dev.to/bowmanjd/getting-started-with-httpx-part-4-pytest-asyncio-and-pytesthttpx-asynchronous-version-454d
[HTTPX]: https://www.python-httpx.org/
[asyncio]: https://docs.python.org/3/library/asyncio.html
[Poetry]: https://python-poetry.org/
[pytest_httpx]: https://github.com/Colin-b/pytest_httpx