Trylks
Trylks

Reputation: 1498

pytest requests to fastapi in a separate process

I am trying to have working tests for an API written with FastAPI.

I start the service in a separate process, run the tests with requests to the service, and check if the results are as expected.

I have extracted the key parts into a minimal working example, in the PD.

Running the MWE with the main file works fine. The tests fail, though.

PD: the code is in a GIST, but now also here:

README.md

# Minimal example to ask in StackOverflow

Pytest does not allow to start a process with a service and tests requests to it,
  at least not in the most straightforward way IMHO.

I may be missing something, or I may be doing something wrong.
Hence, I share this short code in a gist, to ask.

## How to run it

The dependencies are: `fastapi pytest requests uvicorn`.
You may install them with your package / environment manager of choice,
  or use `pipenv install` with the provided `Pipfile`.

To run the code in the environment (e.g. `pipenv shell`), run: `python3 mwe.py`.
You should see everything is `OK`.

To run the test, run in the environment: `pytest`.
This does not work for me, the request times out.

mwe.py

import fastapi, multiprocessing, requests, time, uvicorn

app = fastapi.FastAPI()


@app.get('/ok')
def ok():
    return 'OK'


class service:
    def __enter__(self):
        def run_service():
            uvicorn.run('mwe:app', host='0.0.0.0', port=8000, reload=True)
        self.service = multiprocessing.Process(target=run_service)
        self.service.start()
        time.sleep(10)

    def __exit__(self, *args):
        self.service.terminate()


def main():
    with service():
        return requests.get('http://127.0.0.1:8000/ok').ok


if __name__ == '__main__':
    print('🆖🆗'[main()])

Pipfile

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
pytest = "*"
fastapi = "*"
requests = "*"
uvicorn = "*"

[requires]
python_version = "3.10"
python_full_version = "3.10.6"

test_mwe.py

from mwe import main

def test_main():
    assert main()

Upvotes: 0

Views: 788

Answers (1)

RoyalGoose
RoyalGoose

Reputation: 533

Example for testing from official docs

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()


@app.get("/")
async def read_main():
    return {"msg": "Hello World"}


client = TestClient(app)


def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"msg": "Hello World"}

So, for you example from attached git it can be rewrited to something like this:

def test_get_ok():
    response = client.get("/ok")
    assert response.status_code == 200
    assert response.text() == 'OK'

In a nutshell, it is difficult to describe how to test API correctly, but you can take as an example an excellent template for designing RESTfull API on FastAPI in which there are examples of autotests written just with the Pytest

Upvotes: 1

Related Questions