6.9 KiB
Testando
Graças ao Starlette, testar aplicativos FastAPI é fácil e agradável.
Ele é baseado no HTTPX, que por sua vez é projetado com base em Requests, por isso é muito familiar e intuitivo.
Com ele, você pode usar o pytest diretamente com FastAPI.
Usando TestClient
/// info | "Informação"
Para usar o TestClient
, primeiro instale o httpx
.
Certifique-se de criar um ambiente virtual{.internal-link target=_blank}, ativá-lo e instalá-lo, por exemplo:
$ pip install httpx
///
Importe TestClient
.
Crie um TestClient
passando seu aplicativo FastAPI para ele.
Crie funções com um nome que comece com test_
(essa é a convenção padrão do pytest
).
Use o objeto TestClient
da mesma forma que você faz com httpx
.
Escreva instruções assert
simples com as expressões Python padrão que você precisa verificar (novamente, pytest
padrão).
{!../../docs_src/app_testing/tutorial001.py!}
/// tip | "Dica"
Observe que as funções de teste são def
normais, não async def
.
E as chamadas para o cliente também são chamadas normais, não usando await
.
Isso permite que você use pytest
diretamente sem complicações.
///
/// note | "Detalhes técnicos"
Você também pode usar from starlette.testclient import TestClient
.
FastAPI fornece o mesmo starlette.testclient
que fastapi.testclient
apenas como uma conveniência para você, o desenvolvedor. Mas ele vem diretamente da Starlette.
///
/// tip | "Dica"
Se você quiser chamar funções async
em seus testes além de enviar solicitações ao seu aplicativo FastAPI (por exemplo, funções de banco de dados assíncronas), dê uma olhada em Testes assíncronos{.internal-link target=_blank} no tutorial avançado.
///
Separando testes
Em uma aplicação real, você provavelmente teria seus testes em um arquivo diferente.
E seu aplicativo FastAPI também pode ser composto de vários arquivos/módulos, etc.
Arquivo do aplicativo FastAPI
Digamos que você tenha uma estrutura de arquivo conforme descrito em Aplicativos maiores{.internal-link target=_blank}:
.
├── app
│ ├── __init__.py
│ └── main.py
No arquivo main.py
você tem seu aplicativo FastAPI:
{!../../docs_src/app_testing/main.py!}
Arquivo de teste
Então você poderia ter um arquivo test_main.py
com seus testes. Ele poderia estar no mesmo pacote Python (o mesmo diretório com um arquivo __init__.py
):
.
├── app
│ ├── __init__.py
│ ├── main.py
│ └── test_main.py
Como esse arquivo está no mesmo pacote, você pode usar importações relativas para importar o objeto app
do módulo main
(main.py
):
{!../../docs_src/app_testing/test_main.py!}
...e ter o código para os testes como antes.
Testando: exemplo estendido
Agora vamos estender este exemplo e adicionar mais detalhes para ver como testar diferentes partes.
Arquivo de aplicativo FastAPI estendido
Vamos continuar com a mesma estrutura de arquivo de antes:
.
├── app
│ ├── __init__.py
│ ├── main.py
│ └── test_main.py
Digamos que agora o arquivo main.py
com seu aplicativo FastAPI tenha algumas outras operações de rotas.
Ele tem uma operação GET
que pode retornar um erro.
Ele tem uma operação POST
que pode retornar vários erros.
Ambas as operações de rotas requerem um cabeçalho X-Token
.
//// tab | Python 3.10+
{!> ../../docs_src/app_testing/app_b_an_py310/main.py!}
////
//// tab | Python 3.9+
{!> ../../docs_src/app_testing/app_b_an_py39/main.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/app_testing/app_b_an/main.py!}
////
//// tab | Python 3.10+ non-Annotated
/// tip | "Dica"
Prefira usar a versão Annotated
se possível.
///
{!> ../../docs_src/app_testing/app_b_py310/main.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | "Dica"
Prefira usar a versão Annotated
se possível.
///
{!> ../../docs_src/app_testing/app_b/main.py!}
////
Arquivo de teste estendido
Você pode então atualizar test_main.py
com os testes estendidos:
{!> ../../docs_src/app_testing/app_b/test_main.py!}
Sempre que você precisar que o cliente passe informações na requisição e não souber como, você pode pesquisar (no Google) como fazer isso no httpx
, ou até mesmo como fazer isso com requests
, já que o design do HTTPX é baseado no design do Requests.
Depois é só fazer o mesmo nos seus testes.
Por exemplo:
- Para passar um parâmetro path ou query, adicione-o à própria URL.
- Para passar um corpo JSON, passe um objeto Python (por exemplo, um
dict
) para o parâmetrojson
. - Se você precisar enviar Dados de Formulário em vez de JSON, use o parâmetro
data
. - Para passar headers, use um
dict
no parâmetroheaders
. - Para cookies, um
dict
no parâmetrocookies
.
Para mais informações sobre como passar dados para o backend (usando httpx
ou TestClient
), consulte a documentação do HTTPX.
/// info | "Informação"
Observe que o TestClient
recebe dados que podem ser convertidos para JSON, não para modelos Pydantic.
Se você tiver um modelo Pydantic em seu teste e quiser enviar seus dados para o aplicativo durante o teste, poderá usar o jsonable_encoder
descrito em Codificador compatível com JSON{.internal-link target=_blank}.
///
Execute-o
Depois disso, você só precisa instalar o pytest
.
Certifique-se de criar um ambiente virtual{.internal-link target=_blank}, ativá-lo e instalá-lo, por exemplo:
$ pip install pytest
---> 100%
Ele detectará os arquivos e os testes automaticamente, os executará e informará os resultados para você.
Execute os testes com:
$ 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 <span style="color: green; white-space: pre;">...... [100%]</span>
<span style="color: green;">================= 1 passed in 0.03s =================</span>