# Testing { #testing } Thanks to [Starlette](https://www.starlette.dev/testclient/), testing **FastAPI** applications is easy and enjoyable. It is based on [HTTPX](https://www.python-httpx.org), which in turn is designed based on Requests, so it's very familiar and intuitive. With it, you can use [pytest](https://docs.pytest.org/) directly with **FastAPI**. ## Using `TestClient` { #using-testclient } /// note To use `TestClient`, first install [`httpx`](https://www.python-httpx.org). Make sure you create a [virtual environment](../virtual-environments.md), activate it, and then install it, for example: ```console $ pip install httpx ``` /// Import `TestClient`. Create a `TestClient` by passing your **FastAPI** application to it. Create functions with a name that starts with `test_` (this is standard `pytest` conventions). Use the `TestClient` object the same way as you do with `httpx`. Write simple `assert` statements with the standard Python expressions that you need to check (again, standard `pytest`). {* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *} /// tip Notice that the testing functions are normal `def`, not `async def`. And the calls to the client are also normal calls, not using `await`. This allows you to use `pytest` directly without complications. /// /// note | Technical Details You could also use `from starlette.testclient import TestClient`. **FastAPI** provides the same `starlette.testclient` as `fastapi.testclient` just as a convenience for you, the developer. But it comes directly from Starlette. /// /// tip If you want to call `async` functions in your tests apart from sending requests to your FastAPI application (e.g. asynchronous database functions), have a look at the [Async Tests](../advanced/async-tests.md) in the advanced tutorial. /// ## Separating tests { #separating-tests } In a real application, you probably would have your tests in a different file. And your **FastAPI** application might also be composed of several files/modules, etc. ### **FastAPI** app file { #fastapi-app-file } Let's say you have a file structure as described in [Bigger Applications](bigger-applications.md): ``` . ├── app │   ├── __init__.py │   └── main.py ``` In the file `main.py` you have your **FastAPI** app: {* ../../docs_src/app_testing/app_a_py310/main.py *} ### Testing file { #testing-file } Then you could have a file `test_main.py` with your tests. It could live on the same Python package (the same directory with a `__init__.py` file): ``` hl_lines="5" . ├── app │   ├── __init__.py │   ├── main.py │   └── test_main.py ``` Because this file is in the same package, you can use relative imports to import the object `app` from the `main` module (`main.py`): {* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *} ...and have the code for the tests just like before. ## Testing: extended example { #testing-extended-example } Now let's extend this example and add more details to see how to test different parts. ### Extended **FastAPI** app file { #extended-fastapi-app-file } Let's continue with the same file structure as before: ``` . ├── app │   ├── __init__.py │   ├── main.py │   └── test_main.py ``` Let's say that now the file `main.py` with your **FastAPI** app has some other **path operations**. It has a `GET` operation that could return an error. It has a `POST` operation that could return several errors. Both *path operations* require an `X-Token` header. {* ../../docs_src/app_testing/app_b_an_py310/main.py *} ### Extended testing file { #extended-testing-file } You could then update `test_main.py` with the extended tests: {* ../../docs_src/app_testing/app_b_an_py310/test_main.py *} Whenever you need the client to pass information in the request and you don't know how to, you can search (Google) how to do it in `httpx`, or even how to do it with `requests`, as HTTPX's design is based on Requests' design. Then you just do the same in your tests. E.g.: * To pass a *path* or *query* parameter, add it to the URL itself. * To pass a JSON body, pass a Python object (e.g. a `dict`) to the parameter `json`. * If you need to send *Form Data* instead of JSON, use the `data` parameter instead. * To pass *headers*, use a `dict` in the `headers` parameter. * For *cookies*, a `dict` in the `cookies` parameter. For more information about how to pass data to the backend (using `httpx` or the `TestClient`) check the [HTTPX documentation](https://www.python-httpx.org). /// note Note that the `TestClient` receives data that can be converted to JSON, not Pydantic models. If you have a Pydantic model in your test and you want to send its data to the application during testing, you can use the `jsonable_encoder` described in [JSON Compatible Encoder](encoder.md). /// ## Run it { #run-it } After that, you just need to install `pytest`. Make sure you create a [virtual environment](../virtual-environments.md), activate it, and then install it, for example:
```console $ pip install pytest ---> 100% ```
It will detect the files and tests automatically, execute them, and report the results back to you. Run the tests with:
```console $ pytest ================ test session starts ================ platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: /home/user/code/superawesome-cli/app plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1 collected 6 items ---> 100% test_main.py ...... [100%] ================= 1 passed in 0.03s ================= ```