1# Pruebas { #testing }23Gracias a [Starlette](https://starlette.dev/testclient/), escribir pruebas para aplicaciones de **FastAPI** es fácil y agradable.45Está basado en [HTTPX](https://www.python-httpx.org), que a su vez está diseñado basado en Requests, por lo que es muy familiar e intuitivo.67Con él, puedes usar [pytest](https://docs.pytest.org/) directamente con **FastAPI**.89## Usando `TestClient` { #using-testclient }1011/// note | Nota1213Para usar `TestClient`, primero instala [`httpx`](https://www.python-httpx.org).1415Añádelo a tu proyecto:1617```console18$ uv add httpx19```2021///2223Importa `TestClient`.2425Crea un `TestClient` pasándole tu aplicación de **FastAPI**.2627Crea funciones con un nombre que comience con `test_` (esta es la convención estándar de `pytest`).2829Usa el objeto `TestClient` de la misma manera que con `httpx`.3031Escribe statements `assert` simples con las expresiones estándar de Python que necesites revisar (otra vez, estándar de `pytest`).3233{* ../../docs_src/app_testing/tutorial001_py310.py hl[2,12,15:18] *}3435/// tip | Consejo3637Nota que las funciones de prueba son `def` normales, no `async def`.3839Y las llamadas al cliente también son llamadas normales, sin usar `await`.4041Esto te permite usar `pytest` directamente sin complicaciones.4243///4445/// note | Detalles técnicos4647También podrías usar `from starlette.testclient import TestClient`.4849**FastAPI** proporciona el mismo `starlette.testclient` como `fastapi.testclient` solo por conveniencia para ti, el desarrollador. Pero proviene directamente de Starlette.5051///5253/// tip | Consejo5455Si quieres llamar a funciones `async` en tus pruebas además de enviar requests a tu aplicación FastAPI (por ejemplo, funciones asincrónicas de bases de datos), echa un vistazo a las [Pruebas Asincrónicas](../advanced/async-tests.md) en el tutorial avanzado.5657///5859## Separando pruebas { #separating-tests }6061En una aplicación real, probablemente tendrías tus pruebas en un archivo diferente.6263Y tu aplicación de **FastAPI** también podría estar compuesta de varios archivos/módulos, etc.6465### Archivo de aplicación **FastAPI** { #fastapi-app-file }6667Digamos que tienes una estructura de archivos como se describe en [Aplicaciones Más Grandes](bigger-applications.md):6869```70.71├── app72│ ├── __init__.py73│ └── main.py74```7576En el archivo `main.py` tienes tu aplicación de **FastAPI**:777879{* ../../docs_src/app_testing/app_a_py310/main.py *}8081### Archivo de prueba { #testing-file }8283Entonces podrías tener un archivo `test_main.py` con tus pruebas. Podría estar en el mismo paquete de Python (el mismo directorio con un archivo `__init__.py`):8485``` hl_lines="5"86.87├── app88│ ├── __init__.py89│ ├── main.py90│ └── test_main.py91```9293Debido a que este archivo está en el mismo paquete, puedes usar imports relativos para importar el objeto `app` desde el módulo `main` (`main.py`):9495{* ../../docs_src/app_testing/app_a_py310/test_main.py hl[3] *}969798...y tener el código para las pruebas tal como antes.99100## Pruebas: ejemplo extendido { #testing-extended-example }101102Ahora extendamos este ejemplo y añade más detalles para ver cómo escribir pruebas para diferentes partes.103104### Archivo de aplicación **FastAPI** extendido { #extended-fastapi-app-file }105106Continuemos con la misma estructura de archivos que antes:107108```109.110├── app111│ ├── __init__.py112│ ├── main.py113│ └── test_main.py114```115116Digamos que ahora el archivo `main.py` con tu aplicación de **FastAPI** tiene algunas otras **path operations**.117118Tiene una operación `GET` que podría devolver un error.119120Tiene una operación `POST` que podría devolver varios errores.121122Ambas *path operations* requieren un `X-Token` header.123124{* ../../docs_src/app_testing/app_b_an_py310/main.py *}125126### Archivo de prueba extendido { #extended-testing-file }127128Podrías entonces actualizar `test_main.py` con las pruebas extendidas:129130{* ../../docs_src/app_testing/app_b_an_py310/test_main.py *}131132133Cada vez que necesites que el cliente pase información en el request y no sepas cómo, puedes buscar (Googlear) cómo hacerlo en `httpx`, o incluso cómo hacerlo con `requests`, dado que el diseño de HTTPX está basado en el diseño de Requests.134135Luego simplemente haces lo mismo en tus pruebas.136137Por ejemplo:138139* Para pasar un parámetro de *path* o *query*, añádelo a la URL misma.140* Para pasar un cuerpo JSON, pasa un objeto de Python (por ejemplo, un `dict`) al parámetro `json`.141* Si necesitas enviar *Form Data* en lugar de JSON, usa el parámetro `data` en su lugar.142* Para pasar *headers*, usa un `dict` en el parámetro `headers`.143* Para *cookies*, un `dict` en el parámetro `cookies`.144145Para más información sobre cómo pasar datos al backend (usando `httpx` o el `TestClient`) revisa la [documentación de HTTPX](https://www.python-httpx.org).146147/// note | Nota148149Ten en cuenta que el `TestClient` recibe datos que pueden ser convertidos a JSON, no modelos de Pydantic.150151Si tienes un modelo de Pydantic en tu prueba y quieres enviar sus datos a la aplicación durante las pruebas, puedes usar el `jsonable_encoder` descrito en [Codificador Compatible con JSON](encoder.md).152153///154155## Ejecútalo { #run-it }156157Después de eso, solo necesitas instalar `pytest`.158159Añádelo a tu proyecto:160161<div class="termy">162163```console164$ uv add pytest165166---> 100%167```168169</div>170171Detectará los archivos y pruebas automáticamente, ejecutará las mismas y te reportará los resultados.172173Ejecuta las pruebas con:174175<div class="termy">176177```console178$ uv run pytest179180================ test session starts ================181platform linux -- Python 3.6.9, pytest-5.3.5, py-1.8.1, pluggy-0.13.1182rootdir: /home/user/code/superawesome-cli/app183plugins: forked-1.1.3, xdist-1.31.0, cov-2.8.1184collected 6 items185186---> 100%187188test_main.py <span style="color: green; white-space: pre;">...... [100%]</span>189190<span style="color: green;">================= 1 passed in 0.03s =================</span>191```192193</div>
Findings
✓ No findings reported for this file.