You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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âmetro json.
  • 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âmetro headers.
  • Para cookies, um dict no parâmetro cookies.

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>