Introdução
A avaliação é fundamental no processo de desenvolvimento de software, garantindo que o código se comporte conforme o esperado e esteja livre de defeitos. Em Python, o pytest
é um framework de avaliação popular que oferece vantagens sobre o módulo padrão unit test
, que é um framework de avaliação embutido em Python e faz parte da biblioteca padrão. O pytest
inclui uma sintaxe simples, melhor saída, ferramentas poderosas e um rico ecossistema de extensões. Este tutorial irá guiar você pelo processo de configuração de uma aplicação Flask, pela integração de ferramentas do pytest
e pela escrita de avaliações unitárias usando o pytest
.
Pré-requisitos
Antes de começar, você precisará do seguinte:
-
Um servidor rodando Ubuntu e um usuário não-root com privilégios de sudo e uma firewall ativa. Para orientação sobre como configurar isso, por favor escolha sua distribuição de Ubuntu da lista e siga com o guia de configuração inicial do servidor. Certifique-se de trabalhar com uma versão suportada do Ubuntu.
-
Familiaridade com a linha de comando do Linux. Você pode visitar esta guia sobre primeiro Linux command line.
-
Um entendimento básico do processamento de linguagem Python e do framework de teste
pytest
em Python. Você pode referir-se à nossa tutorial sobre Framework de Teste Python pytest para saber mais sobrepytest
. -
Python 3.7 ou superior instalado no seu sistema Ubuntu. Para aprender a executar um script de Python no Ubuntu, você pode referir-se à nossa tutorial sobre Como executar um script de Python no Ubuntu.
Porque pytest
é uma Alternativa Melhorado ao unittest
pytest
oferece várias vantagens sobre o framework de teste interno unittest
:
-
Pytest permite que você escreva testes com menos código de modelo, usando simples declarações assert em vez das métodos mais verbosos necessários por
unittest
. -
Ele fornece saídas mais detalhadas e legíveis, tornando mais fácil identificar onde e por que um teste falhou.
-
Fixtures de Pytest permitem configurações de teste mais flexíveis e reutilizáveis do que os métodos
setUp
etearDown
de unittest. -
Ele facilita a execução da mesma função de teste com vários conjuntos de entradas, o que não é tão direto em
unittest
. -
Pytest possui uma rica coleção de plugins que extendem suas funcionalidades, desde ferramentas de cobertura de código até execução de testes em paralelo.
-
Ele automaticamente descobre arquivos de teste e funções que correspondem às suas convenções de nomenclatura, economizando tempo e esforço na gerencia de suites de teste.
Dada essas vantagens, pytest
é frequentemente a escolha preferida para testes em Python moderno. Vamos configurar uma aplicação Flask e escrever testes unitários usando pytest
.
Passo 1 – Configurando o Ambiente
O Ubuntu 24.04 vem com Python 3 por padrão. Abra o terminal e execute o comando a seguir para verificar a instalação do Python 3:
Se o Python 3 já estiver instalado no seu computador, o comando acima retornará a versão atual da instalação do Python 3. Caso contrário, você pode executar o seguinte comando para obter a instalação do Python 3:
A próxima etapa é instalar o gerenciador de pacotes pip
no seu sistema:
Uma vez que o pip
estiver instalado, vamos instalar o Flask.
Passo 2 – Criar uma Aplicação Flask
Vamos começar criando uma aplicação Flask simples. Crie um novo diretório para seu projeto e navegue até ele:
Agora, vamos criar e ativar um ambiente virtual para gerenciar dependências:
Instale o Flask usando o pip
:
Agora, vamos criar uma simples aplicação Flask. Crie um novo arquivo chamado app.py
e adicione o código seguinte:
Esta aplicação tem três rotas:
/
: Retorna uma mensagem simples “Hello, Flask!”./about
: Retorna uma mensagem simples “This is the About page”./multiply/<int:x>/<int:y>
: Multiplica dois inteiros e retorna o resultado.
Para executar a aplicação, execute o comando a seguir:
Ao examinar a saída acima, você pode notar que o servidor está executando em http://127.0.0.1
e está escutando na porta 5000
. Abra outra consola Ubuntu e execute os comandos curl
abaixo um por um:
- GET:
curl http://127.0.0.1:5000/
- GET:
curl http://127.0.0.1:5000/about
- GET:
curl http://127.0.0.1:5000/multiply/10/20
Vamos entender o que as solicitações GET fazem:
-
curl http://127.0.0.1:5000/
:
Isto envia uma solicitação GET para a rota raiz (‘/’) de nossa aplicação Flask. O servidor responde com um objeto JSON que contém a mensagem “Hello, Flask!”, demonstrando a funcionalidade básica de nossa rota inicial. -
curl http://127.0.0.1:5000/about
:
Isto envia uma solicitação GET para a rota/about
. O servidor responde com um objeto JSON que contém a mensagem “This is the About page”. Isto mostra que nossa rota está funcionando corretamente. -
curl http://127.0.0.1:5000/multiply/10/20
:
Isto envia uma solicitação GET para a rota/multiply
com dois parâmetros: 10 e 20. O servidor multiplica estes números e responde com um objeto JSON que contém o resultado (200). Isto demonstra que nossa rota de multiplicação pode processar corretamente parâmetros da URL e realizar cálculos.
Estas GET
requests permitem que interajamos com as API endpoints de nossa aplicação Flask, recuperando informação ou disparando ações no servidor sem modificar quaisquer dados. Elas são úteis para buscar dados, testar a funcionalidade de endpoint e verificar que nossas rotas estão respondendo como esperado.
Vamos ver cada uma destas GET
requests em ação:
Passo 3 – Instalando pytest
e Escrevendo seu Primeiro Teste
Agora que você tem uma aplicação Flask básica, vamos instalar pytest
e escrever alguns testes unitários.
Instale pytest
usando pip
:
Crie um diretório chamado tests para armazenar seus arquivos de teste:
Agora, vamos criar um novo arquivo chamado test_app.py
e adicionar o seguinte código:
Vamos analisar as funções neste arquivo de teste:
-
@pytest.fixture def client()
:
Esta é uma fixture de pytest que cria um cliente de teste para nosso aplicativo Flask. Ela usa o métodoapp.test_client()
para criar um cliente que pode enviar solicitações para nossa aplicação sem executar o servidor real. A instruçãoyield
permite que o cliente seja usado em testes e, em seguida, fechado corretamente após cada teste. -
def test_home(client):
Esta função testa a rota home (
/
) do nosso aplicativo. Ela envia uma solicitação GET para a rota usando o cliente de teste, então afirma que o código de status da resposta é 200 (OK) e que a resposta JSON corresponde à mensagem esperada. -
def test_about(client):
Parecido com
test_home
, esta função testa a rota sobre (/about
). Ela verifica por um código de status 200 e confirma o conteúdo da resposta JSON. -
def test_multiply(client):
Esta função testa a rota de multiplicar com entrada válida (
/multiply/3/4
). Ela verifica que o código de status é 200 e que a resposta JSON contém o resultado correto da multiplicação. -
def test_multiply_invalid_input(client)
:
Esta função testa a rota de multiplicação com entrada inválida (multiply/three/four
). Ela verifica se o código de status é 404 (Não Encontrado), o que é o comportamento esperado quando a rota não consegue corresponder as entradas de string aos parâmetros inteiros necessários. -
def test_non_existent_route(client)
:
Esta função testa o comportamento do aplicativo quando uma rota não existente é acessada. Ela envia uma solicitação GET para/non-existent
, que não está definida em nosso aplicativo Flask. O teste afirma que o código de status da resposta é 404 (Não Encontrado), garantindo que o nosso aplicativo trata corretamente solicitudes a rotas não definidas.
Estes testes abrangem a funcionalidade básica do nosso aplicativo Flask, garantindo que cada rota responda corretamente a entradas válidas e que a rota de multiplicação trata entradas inválidas apropriadamente. Utilizando pytest
, podemos executar facilmente estes testes para verificar que o nosso aplicativo está funcionando conforme esperado.
Passo 4 – Executar as Testes
Para executar as testes, execute o seguinte comando:
Por padrão, o processo de descoberta de pytest
irá varrer recursivamente a pasta atual e suas subpastas procurando arquivos que começam com nomes que contenham “test_” ou terminem com “_test”. Os testes localizados nestes arquivos então serão executados. Você deveria ver saídas semelhantes a:
Isso indica que todos os testes passaram com sucesso.
Passo 5: Usando Fixtures no pytest
Fixtures são funções que são usadas para fornecer dados ou recursos aos testes. Elas podem ser usadas para configurar e desconfigurar ambientes de teste, carregar dados ou realizar outras tarefas de configuração. No pytest
, as fixtures são definidas usando o decorador @pytest.fixture
.
Veja como melhorar a fixture existente. Atualize a fixture de cliente para usar lógica de configuração e desconfiguração:
Este setup adiciona declarações de impressão para demonstrar as fases de setup e teardown no output dos testes. Essas podem ser substituídas por código de gerenciamento de recursos até necessário.
Vamos tentar executar os testes novamente:
A flag -v
aumenta a verbosidade, e a flag -s
permite que declarações de impressão sejam exibidas na saída do console.
Você deve ver a seguinte saída:
Step 6: Adding a Failure Test Case
Vamos adicionar um caso de teste de falha ao arquivo de teste existente. Modifique o arquivo test_app.py
e adicione a função abaixo no final para um caso de teste de falha com um resultado incorreto:
Vamos desconstruir a função test_multiply_edge_cases
e explicar o que cada parte faz:
-
Test with zero:
Este teste verifica se a função de multiplicação corretamente handle a multiplicação por zero. Esperamos que o resultado seja 0 quando multiplicando qualquer número por zero. Esta é uma importante condição de borda a ser testada, porque algumas implementações podem ter problemas com a multiplicação por zero. -
Teste com números grandes:
Este teste verifica se a função de multiplicação pode lidar com números grandes sem estourar ou com problemas de precisão. Estamos multiplicando dois valores de um milhão, esperando um resultado de um bilião. Este teste é crucial porque verifica os limites superiores das capacidades da função. Note que isso poderia falhar se a implementação do servidor não lidar corretamente com números grandes, o que poderia indicar a necessidade de bibliotecas de números grandes ou um tipo de dado diferente. -
Teste propositalmente defeituoso:
Este teste está deliberadamente configurado para falhar. Ele verifica se 2 * 3 é igual a 7, o que é incorreto. Este teste visa demonstrar o aspecto de um teste defeituoso no resultado de testes. Isto ajuda a entender como identificar e debugar testes defeituosos, que é uma habilidade essencial em desenvolvimento de testes dirigidos e processos de depuração.
Ao incluir esses casos de borda e um defeito intencional, você está testando não só a funcionalidade básica da sua rota de multiplicação, mas também seu comportamento em condições extremas e suas capacidades de relatório de erro. Esta abordagem de teste ajuda a garantir a robustez e a confiabilidade da nossa aplicação.
Vamos tentar executar os testes novamente:
Você deveria ver o seguinte output:
A mensagem de falha acima indica que o teste test_multiply_edge_cases
no arquivo tests/test_app.py
falhou. especificamente, a última afirmação neste método de teste causou o falha.
Este defeito intencional é útil para demonstrar como os avisos de falha dos testes são relatados e quais informações são fornecidas na mensagem de falha. Ele mostra exatamente na linha onde ocorreu o erro, os valores esperados e reais, e a diferença entre eles.
Em um cenário real, você corrigiria o código para tornar o teste passar ou ajustaria o teste se o resultado esperado estivesse incorreto. No entanto, neste caso, a falha é intencional por finalidades educacionais.
Conclusão
Neste tutorial, nós abordamos como configurar testes unitários para uma aplicação Flask usando pytest
, integrando fixtures pytest
e mostrando o que uma falha de teste se parece. Ao seguir essas etapas, você pode garantir que suas aplicações Flask são confiáveis e manutenveis, minimizando bugs e melhorando a qualidade do código.
Você pode referir-se à documentação oficial de Flask e Pytest para aprender mais.
Source:
https://www.digitalocean.com/community/tutorials/unit-test-in-flask