Ter uma boa bateria de testes para seu código pode ser um requisito para muitos projetos Python. Na prática, escrever testes unitários é difícil e pode exigir muito tempo e esforço. Por isso, alguns desenvolvedores não gostam de escrevê-los. Entretanto, com o grandes modelos de linguagem (LLMs) e ferramentas como ChatGPTo senhor pode criar rapidamente conjuntos de testes robustos e completos para seu código Python.
Em Python, o senhor pode usar várias ferramentas diferentes para escrever testes. As ferramentas mais comumente usadas incluem doctest
, unittest
, e pytest
. O ChatGPT pode ser de grande ajuda para escrever testes com qualquer uma dessas ferramentas.
Neste tutorial, o senhor verá:
- Solicitar ao ChatGPT que crie testes usando
doctest
- Use o ChatGPT para escrever
unittest
testes, instalações e suítes - Crie prompts do ChatGPT para escrever
pytest
Testes e fixtures - Use prompts alternativos para casos em que o código não está disponível
Para tirar o máximo proveito deste tutorial, o senhor deve configurar uma conta do ChatGPT e conhecer as noções básicas de interação com essa ferramenta usando o engenharia imediata. O senhor também deve conhecer os princípios básicos de como testar o código em Python.
Benefícios de usar o ChatGPT para testar o código Python
Ter um código bom e atualizado testes unitários para o seu código é essencial para qualquer projeto Python. Um código mal testado ou sem testes pode acabar sendo pouco confiável e fraco. Com testes automatizados, o senhor pode garantir e mostrar que seu código funciona corretamente em diferentes cenários. Portanto, ter testes é importante do ponto de vista técnico e comercial.
Escrever bons testes é difícil e pode levar muito tempo. É por isso que alguns desenvolvedores não gostam de escrevê-los. Usando modelos de linguagem grandes (LLM) como ChatGPT pode ser uma alternativa viável para fornecer testes adequados aos seus projetos e códigos.
Observação: O senhor pode usar o ChatGPT e outros LLMs de várias maneiras úteis no contexto do desenvolvimento do Python. Confira os recursos a seguir para conhecer outros casos de uso e insights úteis:
Alguns dos benefícios de usar o ChatGPT para escrever testes para seu código Python incluem o seguinte:
- Eficiência e velocidade: Ele pode gerar testes de unidade com base em especificações ou trechos de código. Essa possibilidade reduz significativamente o tempo que o senhor precisa gastar escrevendo testes. Assim, o senhor pode se concentrar em escrever a lógica do aplicativo.
- Melhoria da cobertura: Ele pode sugerir testes para casos extremos ou cenários que os desenvolvedores talvez não considerem imediatamente. Dessa forma, o senhor pode melhorar o teste do seu código cobertura.
- Redução de erros: Pode reduzir o erro humano ao escrever códigos de teste repetitivos ou padronizados.
- Aprendizado e integração: Pode servir como uma ferramenta educacional para desenvolvedores que são novos em estruturas de teste ou que não estão familiarizados com as práticas recomendadas de teste de unidade. Os testes gerados podem ajudar os desenvolvedores a aprender sobre padrões de teste, asserçõese maneiras de escrever testes de forma eficaz.
Com o ChatGPT, o senhor pode gerar testes de unidade para o seu código Python em quase nenhum momento. No entanto, é preciso observar que, embora os testes gerados possam parecer bons, o senhor ainda deve revisar e possivelmente refinar os testes gerados.
Observação: Para este tutorial, o senhor usará uma conta gratuita do ChatGPT que é alimentada pelo GPT-3.5 LLM. O senhor pode usar esse modelo gratuitamente com o modelo padrão interface da Web padrão da OpenAI. Se o senhor usar uma conta paga com o GPT-4, seus resultados poderão ser mais precisos e rápidos.
Além disso, o senhor usará um tópico de bate-papo individual para cada seção principal do tutorial. Portanto, o senhor usará tópicos diferentes para o doctest
, unittest
, e pytest
seções.
O uso de um único thread de chat para executar todos os exemplos deste tutorial pode fazer com que o chat gere respostas significativamente diferentes devido ao contexto passado, que inclui prompts e respostas anteriores.
Nas seções a seguir, o senhor aprenderá os conceitos básicos do uso do ChatGPT como assistente para criar testes unitários coerentes para seus projetos Python usando diferentes estruturas e bibliotecas de teste.
Redação doctest
Testes com ChatGPT
O doctest
do Python fornece um módulo leve de estrutura de testes que o senhor pode usar para automação de testes. Ele pode ler os casos de teste da documentação do seu projeto e das docstrings do seu código. Essa estrutura vem com o interpretador Python, portanto, o senhor a terá à sua disposição com qualquer instalação do Python, o que é ótimo.
Com doctest
, o senhor pode escrever código que fornece exemplos de como seu código funciona, simulando REPL sessões. Esses exemplos funcionam como documentação e também como casos de teste ou testes de unidade. Cada doctest
teste precisa de uma declaração ou expressão e um resultado esperado.
O senhor pode usar o ChatGPT para ajudá-lo a escrever doctest
testes. Primeiro, o senhor precisa de algum código para testar. A função a seguir tenta resolver o problema do FizzBuzz desafio, onde o senhor retorna "fizz"
para números divisíveis por três, "buzz"
para os divisíveis por cinco, e "fizz buzz"
para os que são divisíveis por três e cinco.
Vá em frente e crie um fizzbuzz.py
e adicione o seguinte código a ele:
Essa função funciona bem para números divisíveis por 3
ou 5
. No entanto, há um pequeno problema com números que são divisíveis por ambos. Mesmo que o senhor saiba disso, vá em frente e inicie um novo tópico de chat. Em seguida, peça ao ChatGPT para escrever doctest
para a função:
O senhor: Escreva
doctest
para a seguinte função:ChatGPT:
Com certeza! A função que o senhor forneceu implementa um algoritmo básico do FizzBuzz, mas com um pequeno erro lógico. A verificação da divisibilidade por
15
deve vir antes das verificações de3
e5
, pois todo número divisível por15
também é divisível por ambos3
e5
, mas seu pedido atual nunca chegará ao"fizz buzz"
. Aqui está uma versão corrigida de sua função com a ordem lógica corrigida, seguida pordoctest
que testa a função:Para usá-los
doctest
o senhor precisará incluí-los no docstring da sua função, conforme mostrado acima. Em seguida, o senhor pode executar os testes com o comandodoctest
adicionando o seguinte ao seu script:Esse código executará automaticamente os testes definidos na documentação quando o senhor executar o arquivo Python. Lembre-se de que a ordem corrigida das condições na função garante que os números divisíveis por ambos os
3
e5
retorno"fizz buzz"
que é crucial para a lógica do FizzBuzz.
Uau! Que ótimo! O chat não apenas escreveu o doctest
para o senhor. Ele também corrigiu o problema, explicou conceitos importantes sobre o doctest
e forneceu instruções sobre como executar os testes. Observe que os testes abrangem casos regulares e extremos, o que é bastante conveniente.
Observação: Ao executar os prompts deste tutorial em sua própria instância do ChatGPT, o senhor obterá respostas diferentes.
É fundamental que o senhor entenda que as respostas geradas podem incluir erros, problemas e conceitos incorretos. Portanto, o senhor deve analisar cuidadosamente cada saída e corrigir qualquer problema que encontrar.
Pense no ChatGPT como uma ferramenta de aumento de produtividade em vez de uma fonte de informações ou códigos estritamente corretos.
Execute o seguinte comando na janela do terminal para executar os testes e ver seus resultados:
Depois de executar o comando acima, o senhor verá uma saída detalhada com informações detalhadas sobre cada doctest
teste. Os -v
da linha de comando é responsável por gerar a saída detalhada. Como o senhor pode ver, todos os testes foram aprovados, portanto, sua função agora funciona bem. O LLM fez um ótimo trabalho.
Criando unittest
Testes com o ChatGPT
O unittest
é outra estrutura biblioteca padrão que o senhor pode usar para escrever testes unitários para o seu código. Essa estrutura de teste usa um orientado a objetos e oferece suporte a alguns conceitos essenciais que facilitam o teste de código:
- Caso de teste: Uma unidade individual de teste. Ela examina a saída para um determinado conjunto de entradas.
- Conjunto de testes: Uma coleção de casos de teste, conjuntos de teste ou ambos. Eles são agrupados e executados como um todo.
- Dispositivos de teste: Um dispositivo de teste refere-se a um grupo de ações necessárias para configurar um ambiente para testes. Eles também incluem os processos de desmontagem após a execução dos testes.
- Executor de teste: Um componente que lida com a execução de testes e comunica os resultados ao usuário.
Nas seções a seguir, o senhor escreverá alguns prompts rápidos para que o ChatGPT forneça casos de teste, dispositivos e conjuntos de teste para o senhor.
Escrevendo casos de teste
O unittest
fornece o módulo TestCase
base classeque o senhor pode usar para escrever casos de teste por meio de subclasses. Diferente de doctest
, unittest
é uma ferramenta para criar casos de teste elaborados em módulos independentes que o senhor pode agrupar em um tests/
no diretório raiz do seu projeto ou em qualquer outro local.
Novamente, o senhor pode pedir ao ChatGPT para escrever unittest
para o senhor. Aqui está um prompt rápido para fazer isso. Lembre-se de iniciar um novo tópico de bate-papo antes de executar o prompt:
O senhor: Escreva
unittest
casos de teste para a seguinte função:ChatGPT:
Para escrever
unittest
casos de teste para ofizzbuzz()
o senhor precisa seguir estas etapas:
- Importar o arquivo
unittest
módulo.- Defina uma classe de teste que herda do
unittest.TestCase
.- Escreva métodos de teste dentro dessa classe para testar diferentes aspectos do
fizzbuzz()
função.
- Cada método de teste deve começar com a palavra
test
.- Use asserções como
self.assertEqual()
para verificar a saída da função em relação aos resultados esperados.- Por fim, chame o
unittest.main()
para executar os testes quando o script for executado.Veja como o senhor pode estruturar seus casos de teste para o
fizzbuzz()
:Para executar esses testes, salve o código em um arquivo
.py
e execute-o com o Python. Ounittest
descobrirá automaticamente os métodos de teste emTestFizzBuzz
e os executará, relatando os resultados.
Essa resposta também é excelente! O bate-papo oferece uma ótima explicação de como organizar seus casos de teste quando você estiver usando unittest
. Em seguida, ele gera o código para os testes.
Observe que cada teste inclui várias asserções com diferentes argumentos e resultados. Essa abordagem pode ser adequada quando o senhor precisa testar várias propriedades relacionadas em um objeto. No seu exemplo, essa abordagem funciona bem porque as asserções combinadas testam um único valor de retorno.
O uso de várias asserções ajuda a reduzir o código boilerplate. Em geral, essa abordagem tem os seguintes prós:
- Eficiência: Várias asserções em um único teste podem reduzir o código repetitivo. Isso também pode fazer com que os testes sejam executados mais rapidamente nos cenários em que o senhor tem requisitos de configuração e desmontagem para cada teste.
- Testes contextuais: Talvez sejam necessárias várias asserções para verificar se uma função se comporta corretamente em um contexto específico.
- Conveniência: Várias asserções em um teste podem ser mais simples e menos tediosas de escrever em comparação com a escrita de vários testes de asserção única.
Essa abordagem também tem seus contras:
- Clareza e isolamento: Quando um teste com várias asserções falha, pode ser mais difícil identificar imediatamente qual asserção causou a falha. Isso pode ir contra seu processo de depuração.
- Risco de quebra: Quando uma afirmação inicial em um teste falha, as afirmações subsequentes não são executadas. Isso pode ocultar outros problemas.
- Desfoque da finalidade do teste: Quando um teste tem várias afirmações, ele pode se tornar menos focado. Isso pode tornar o teste mais difícil de entender.
Por fim, o ChatGPT fornece ao senhor instruções rápidas sobre como executar os testes. O senhor já tem um fizzbuzz.py
contendo o arquivo fizzbuzz()
. Portanto, vá em frente e crie o arquivo chamado test_fizzbuzz_unittest.py
e cole somente o código relacionado ao teste:
Nesse arquivo, o senhor copiou o código relacionado ao teste como o chat o gerou. Observe que o senhor importou o código fizzbuzz()
da sua função fizzbuzz.py
para que os testes sejam executados. Agora, vá em frente e execute o seguinte comando para executar os testes:
Esse comando executa o teste a partir do arquivo test_fizzbuzz_unittest.py
usando a interface de linha de comando do unittest
. O -v
gera uma saída detalhada que aproveita as documentações dos testes para fornecer contexto sobre o que é cada teste.
Como o código na resposta do chat inclui o idioma name-main envolvendo o unittest.main()
o senhor também pode executar os testes com executando o test_fizzbuzz_unittest.py
como um script Python comum.
Criação de dispositivos
Um dispositivo de teste é uma preparação que o senhor precisa realizar para um ou mais testes e quaisquer ações de limpeza associadas. O código de configuração pode envolver a criação de arquivos temporários, objetos, bancos de dados, conjuntos de dados, conexões e assim por diante.
Para ilustrar como os dispositivos funcionam no unittest
, digamos que o senhor tenha criado um readers.py
que implementa um arquivo JSONReader
que se parece com o seguinte:
O senhor precisa escrever unittest
para sua classe. Esses testes precisarão de preparação. Por exemplo, o senhor pode escrever um fixture de configuração para criar um arquivo temporário com algum conteúdo de amostra. Em seguida, o senhor pode remover o arquivo após a execução dos testes no estágio de desmontagem.
Aqui está um prompt rápido que o senhor pode usar com o ChatGPT para escrever os dispositivos e os testes apropriados:
O senhor: Escreva
unittest
casos de teste com acessórios para a classe a seguir:ChatGPT:
Para escrever
unittest
casos de teste com acessórios para oJSONReader
o senhor precisará seguir estas etapas:
- Use os métodos de configuração e desmontagem para preparar e limpar os dispositivos de teste. Esses métodos podem ser
.setUp()
(executado antes de cada método de teste) e.tearDown()
(é executado após cada método de teste) para o gerenciamento de recursos.- No método de configuração, crie um arquivo JSON temporário que o
JSONReader
lerá.- Escreva métodos de teste para verificar se o
JSONReader
lê corretamente o conteúdo JSON de um arquivo.- Use o método teardown para limpar todos os recursos, como excluir o arquivo temporário criado para teste.
Veja como o senhor pode implementar essas etapas em um
unittest
caso de teste:Este exemplo demonstra como:
- Usar
.setUp()
para preparar um arquivo JSON temporário que oJSONReader
usará para leitura.- Escreva um teste básico (
.test_read_json()
) para verificar se oJSONReader
pode ler corretamente os dados JSON de um arquivo.- Escreva um teste (
.test_file_not_found()
) para verificar como oJSONReader
se comporta quando o arquivo não existe, esperando umFileNotFoundError
.- Utilização
.tearDown()
para fazer a limpeza, excluindo o arquivo temporário após cada teste.Para executar esses testes, salve o código em um arquivo
.py
e execute-o com o Python. Ounittest
descobrirá e executará automaticamente os testes, informando os resultados.
Em sua resposta, o chat primeiro lista as etapas necessárias para escrever casos de teste e dispositivos para a classe de destino. Em seguida, ele gera o código de teste. O .setUp()
cria o arquivo temporário necessário com alguns dados de amostra usando o método tempfile
da biblioteca padrão. O método .tearDown()
remove o arquivo temporário como uma ação de limpeza. Em geral, o código parece bom e bem organizado.
Observe que o senhor encontrará alguns problemas de estilo de codificação no código gerado. Por exemplo, em vez de formalizar o docstrings, as funções de teste começam com um comentário. Além disso, alguns atributos podem não ter nomes descritivos e, em alguns casos, o senhor encontrará construções desnecessárias, como o uso de um variável descartável no último teste. O senhor pode corrigir manualmente esses problemas para atender aos seus requisitos de estilo de codificação.
O senhor já tem um readers.py
que contém seu arquivo JSONReader
. Vá em frente e crie um arquivo chamado test_readers_unittest.py
e copie o código gerado. Lembre-se de remover a classe e importá-la de seu readers.py
do arquivo. Em seguida, execute o seguinte comando para executar os testes:
Ótimo! Os testes foram aprovados e o código gerado funciona corretamente.
Criando suítes de teste
Usando unittest
, o senhor pode criar conjuntos de testes para agrupar testes. Dessa forma, é possível executar seletivamente um conjunto de testes em seu código, o que pode ser conveniente nas situações em que os testes levam muito tempo para serem executados. Nesse caso, talvez seja necessário um atalho que permita executar apenas o teste relacionado ao código em que está trabalhando.
Para ilustrar como criar testes e agrupá-los com conjuntos de testes usando o ChatGPT, digamos que o senhor tenha um módulo chamado calculations.py
que define operações aritméticas e estatísticas básicas:
O senhor precisa gerar unittest
para todas as funções deste módulo. Aqui está um prompt rápido que o senhor pode usar para concluir essa tarefa:
O senhor: Escreva
unittest
casos de teste para o módulo a seguir:ChatGPT:
Para testar o módulo que o senhor forneceu, que contém funções para operações aritméticas básicas e cálculos estatísticos, é possível seguir a estrutura descrita abaixo. Essa estrutura inclui testes para cada função, garantindo que elas lidem com casos típicos e casos extremos, como a divisão por zero ou o cálculo do modo de um conjunto de dados com vários modos:
Esse conjunto de testes abrange cada função do módulo fornecido. As operações aritméticas são testadas com valores positivos, negativos e zero. As operações estatísticas são testadas com listas de vários comprimentos e composições, incluindo casos extremos:
- Para
divide()
, ele testa a divisão por zero, esperando umValueError
.- Para
mean()
ele testa com listas de tamanhos pares e ímpares.- Para
median()
ele testa tanto o número par quanto o ímpar de elementos na lista, incluindo um teste em que os dados não são inicialmente classificados.- Para
mode()
ele testa tanto quando há um único modo quanto quando há vários modos na lista.Para executar esses testes, certifique-se de que as funções do módulo estejam definidas no mesmo arquivo ou importadas corretamente para o arquivo de teste e, em seguida, execute o arquivo de teste com o Python. O
unittest
descobrirá e executará automaticamente os testes, informando os resultados.
Ótimo! O senhor tem casos de teste para todas as funções do seu calculations.py
do módulo. Os diferentes testes estão agrupados em dois TestCase
subclasses. A primeira agrupa as funções aritméticas básicas e a segunda agrupa as funções estatísticas. Essa é uma ótima maneira de estruturar seus testes.
Há um pequeno detalhe que o senhor deve observar nesse código gerado. O chat está importando o Counter
da classe collections
. Essa importação não é necessária porque o código de teste não usa a classe. Portanto, o senhor pode remover essa importação com segurança.
Antes de tentar executar os testes, vá em frente e importe todas as funções do seu calculations.py
do módulo. Em seguida, execute o seguinte comando, que executa todos os testes do módulo test_calculations.py
:
Todos os testes foram aprovados! Nesse caso, o senhor não usou o -v
da linha de comando para que o senhor não obtenha a saída detalhada.
Agora, digamos que o senhor queira executar o teste de forma independente. Por exemplo, o senhor pode querer executar os testes das funções aritméticas separadamente dos testes das funções estatísticas. O senhor pode usar unittest
para esse fim.
Aqui está um prompt para pedir ajuda ao bate-papo. Lembre-se de permanecer no mesmo tópico de bate-papo:
O senhor: Escreva
unittest
conjuntos de testes para agrupar as funções aritméticas e as funções estatísticas.ChatGPT:
Para agrupar os testes de funções aritméticas e estatísticas em conjuntos de testes separados usando o
unittest
do Python, o senhor pode usar o comandoTestSuite
class:Esse script define duas classes de teste,
TestArithmeticOperations
eTestStatisticalOperations
cada um contendo testes relevantes para sua categoria. Oload_tests()
é usada para criar um conjunto de testes que combina testes de ambas as classes, gerenciando um total de 10 testes. Essa função é um gancho fornecido pelounittest
para personalizar o carregamento de testes e a criação de suítes. Ela é chamada automaticamente quando se usa ounittest.main()
.Para executar os testes, certifique-se de que as funções do seu módulo estejam definidas no mesmo arquivo ou importadas corretamente para o arquivo de teste e, em seguida, execute o arquivo de teste com o Python. O
unittest
descobrirá a estrutura doload_tests()
usará a função para construir o conjunto de testes e executará os testes, relatando os resultados.
Na resposta acima, o chat gerou dois TestCase
que são semelhantes às criadas anteriormente. Em seguida, ele gera o load_tests()
função. Neste exemplo, a função define um conjunto de testes, incluindo os dois casos de teste.
Se o senhor executar o código como está, estará executando todos os testes. No entanto, se o senhor comentar uma das chamadas para .addTests()
em load_tests()
o senhor estará executando testes específicos. Para experimentar esses testes atualizados, vá em frente e substitua o conteúdo de sua função test_calculations.py
pelo código acima. Lembre-se de importar as funções de calculations.py
.
Em seguida, comente a linha que adiciona o TestArithmeticOperations
e execute o seguinte comando:
Quando o senhor comenta a linha que adiciona os testes aritméticos, seu código executa apenas os testes estatísticos.
O uso de suítes de teste tem vários benefícios. Alguns dos mais relevantes são os seguintes:
- Organizar seus testes: O senhor pode usar suítes de teste para agrupar os testes de forma lógica, de modo que eles sejam mais fáceis de manter e de entender.
- Execute seu teste seletivamente: Nas fases de desenvolvimento ou depuração, talvez o senhor queira executar apenas um subconjunto de testes que sejam relevantes para a parte do código em que está trabalhando. O senhor pode fazer isso com conjuntos de testes.
- Melhorar o desempenho ao executar o teste: O senhor pode ter conjuntos de testes para diferentes conjuntos de recursos em seu aplicativo, de modo a evitar a execução de todos os testes sempre que atualizar o código.
As suítes de teste são um recurso poderoso do unittest
que aprimoram a organização, a execução e a manutenção dos testes, tornando-os particularmente úteis em cenários de testes complexos.
Redação pytest
Testes com ChatGPT
Se o senhor já se aprofundou nos testes em Python, conhece o pytest
que é uma estrutura de teste popular para Python. Ele permite que o senhor teste todos os tipos de aplicativos e bibliotecas Python. É conhecida por sua simplicidade, flexibilidade e recursos avançados, que incluem alguns dos seguintes:
- Descoberta automática de testes: Descobre automaticamente os módulos e as funções de teste. Por padrão, ele procura por arquivos denominados
test_*.py
ou*_test.py
e executa todas as funções e métodos cujos nomes começam comtest_*
. - Dispositivos de teste: Oferece um modelo de fixação avançado que o senhor pode usar para configurar e desmontar o ambiente de teste. O senhor pode usar dispositivos para criar objetos, gerenciar recursos ou estabelecer estados antes de uma execução de teste e limpar depois.
- Testes parametrizados: Ele oferece suporte a testes parametrizados, que permitem que o senhor execute testes com vários argumentos diferentes. Esse recurso ajuda a reduzir a duplicação de código e facilita o teste de funções com várias entradas.
- Rica arquitetura de plug-ins: Possui um amplo ecossistema de plug-ins que amplia sua funcionalidade, incluindo execução de testes paralelos, relatórios de cobertura de testes e integração com outras ferramentas.
- Relatórios detalhados: Emite relatórios detalhados sobre a execução do teste. Os relatórios incluem informações sobre os testes que passaram, falharam ou foram ignorados. Também informa os motivos das falhas e erros.
Em resumo, pytest
é uma estrutura de teste flexível e com todos os recursos que simplifica o processo de escrever, organizar e executar testes em Python. Nas seções a seguir, você usará o ChatGPT para escrever pytest
testes, criar testes parametrizados e escrever dispositivos de teste.
Escrevendo testes
Em pytest
, o senhor pode escrever testes como funções normais. O senhor não precisa fazer uma subclasse de uma classe base ou usar métodos específicos da API de uma estrutura. Portanto, escrever testes com pytest
é rápido e flexível.
Para escrever alguns pytest
com o ChatGPT, inicie um novo tópico de bate-papo. Em seguida, emita o seguinte prompt:
O senhor: Escreva
pytest
casos de teste para a seguinte função:ChatGPT:
Com certeza! Para escrever
pytest
casos de teste para ofizzbuzz()
o senhor precisa primeiro se certificar de que tem a funçãopytest
instalado. Se não estiver instalado, o senhor pode instalá-lo usandopip install pytest
.Aqui estão alguns exemplos de casos de teste que abrangem todas as ramificações do
fizzbuzz()
da função:Para executar esses testes, o senhor os salvará em um arquivo (digamos
test_fizzbuzz.py
) e, em seguida, executarpytest
no terminal, no diretório em que seu arquivo de teste está localizado. O Pytest descobrirá automaticamente os testes que são prefixados comtest_
e os executará.
Nessa resposta, o senhor tem cinco funções de teste separadas. Cada função testa um cenário diferente. É importante observar que o senhor não precisa importar pytest
no início do módulo para que o código funcione.
Observe que o ChatGPT gerou funções com uma única asserção cada. Essa abordagem é diferente do que foi feito com a função unittest
testes. Em geral, o uso de uma única asserção por teste tem as seguintes vantagens:
- Clareza e foco: Os testes com asserções únicas tendem a ser mais focados em um resultado esperado específico.
- Depuração e manutenção: Os testes de asserção única falham e fica imediatamente claro o que deu errado, pois há apenas um motivo para a falha.
- Granularidade nos resultados dos testes: Os testes de asserção única fornecem uma visão granular da funcionalidade que o teste está verificando.
Os testes de asserção única também têm alguns contras:
- Aumento do número de testes: Ter uma asserção por teste pode levar a um grande número de funções de teste, o que pode desordenar o conjunto de testes e dificultar a navegação e a manutenção.
- Sobrecarga de desempenho: A execução de um grande número de testes pode ser mais lenta do que a execução de um número menor. Por exemplo, a repetição do mesmo código de configuração em vários testes pode causar sobrecarga de desempenho.
Como diz ChatGPT, o senhor precisa instalar o pytest
para poder executar esses testes. Então, vá em frente e execute o seguinte comando em seu Python ambiente:
Este comando fará o download pytest
do site do Índice de pacotes Python (PyPI) e instale-o em seu ambiente Python atual.
Agora, o senhor está pronto para executar os testes gerados. Vá em frente e crie um arquivo chamado test_fizzbuzz_pytest.py
e adicione o código acima a ele. Lembre-se de importar seu fizzbuzz()
. O senhor também pode remover a função pytest
import. Quando o arquivo estiver no lugar, execute o seguinte comando:
Seus testes funcionam como esperado. Eles testam quatro cenários diferentes e seu código é aprovado em todos eles.
Parametrização de testes
Como o senhor já aprendeu, pytest
permite que o senhor parametrize as funções de teste. Essa parametrização é muito útil, pois permite que o senhor não precise escrever uma função de teste para cada conjunto de parâmetros. Assim, o senhor pode escrever menos funções de teste e ter mais testes ao mesmo tempo. Isso reduz o código repetitivo e aumenta sua produtividade.
O senhor usará o @pytest.mark.parametrize para definir vários conjuntos de argumentos para uma função ou classe de teste.
Supondo que esteja seguindo o exemplo da seção anterior e que tenha o mesmo thread de chat ativo, é possível usar o seguinte prompt para pedir ao ChatGPT que atualize o teste para você:
O senhor: Atualize os testes anteriores usando a parametrização para evitar repetições.
ChatGPT:
Para atualizar os casos de teste anteriores para o
fizzbuzz
usando o recurso de parametrização do pytest, podemos consolidá-los em uma única função de teste que usa diferentes valores de entrada e saídas esperadas como parâmetros. Essa abordagem reduz a repetição e torna o conjunto de testes mais conciso e de fácil manutenção. Veja como o senhor pode fazer isso:Nesta versão atualizada, o
@pytest.mark.parametrize
é usado para executar o decoradortest_fizzbuzz()
várias vezes com diferentes conjuntos de argumentos (input
eexpected
). Cada tupla na lista passada para o decorador representa um caso de teste, em que o primeiro elemento é a entrada para ofizzbuzz()
e o segundo elemento é o resultado esperado.Essa abordagem permite que o senhor cubra uma ampla gama de cenários de teste com uma única função de teste, tornando o código de teste mais limpo e reduzindo a redundância. Além disso, adicionar novos casos de teste é tão simples quanto adicionar uma nova tupla à lista de parâmetros, melhorando a capacidade de manutenção do conjunto de testes.
Agora, o senhor tem uma única função de teste chamada test_fizzbuzz()
. Entretanto, com a parametrização, essa função funciona como oito testes diferentes – um para cada par de parâmetros.
O uso da parametrização nos testes oferece várias vantagens. Ela reduz a duplicação de código, tornando seu conjunto de testes mais conciso. Também melhora a cobertura do teste e simplifica a manutenção do código. Em resumo, a parametrização é um ótimo recurso do pytest
que o senhor acabará adorando.
Atualize seu test_fizzbuzz_pytest.py
com o código acima. Em seguida, importe fizzbuzz()
e execute o seguinte comando para executar os testes:
$ python -m pytest test_fizzbuzz_pytest.py
======================== test session starts ========================
platform darwin -- ...
rootdir: .../examples
collected 8 items
test_fizzbuzz_pytest.py ............. [100%]
========================= 8 passed in 0.03s =========================
Na saída, o senhor pode ver que pytest
coletou oito testes no total. Isso significa que ele conta cada conjunto de parâmetros como um teste individual.
Criação de dispositivos
O senhor também pode criar dispositivos de código no pytest
para lidar com a lógica de configuração e desmontagem. Para fazer isso, o senhor pode usar o @pytest.fixture
decorator.
Para continuar com os exemplos de código que o senhor viu até agora, volte ao seu JSONReader
. Agora, emita o seguinte prompt em sua janela do ChatGPT. Lembre-se de continuar na janela pytest
thread:
O senhor: Escreva
pytest
casos de teste com acessórios para a classe a seguir:ChatGPT:
Para escrever
pytest
casos de teste para oJSONReader
incluindo o uso de fixtures para configurar os arquivos de teste necessários, siga as etapas abaixo. Primeiro, certifique-se de que o senhor tenhapytest
instalado.
- Configuração do dispositivo: Crie um dispositivo que configure um arquivo JSON temporário, que será usado pelos testes. Esse acessório criará um arquivo antes da execução de cada teste e o excluirá depois para garantir que os testes não interfiram uns nos outros.
- Casos de teste: Escreva casos de teste para verificar se o
JSONReader
pode ler corretamente os arquivos JSON. Isso inclui testar a leitura correta do conteúdo e o tratamento de possíveis exceções (por exemplo, arquivo não encontrado).Aqui está um exemplo de como o arquivo de teste pode parecer:
Neste exemplo,
tmp_path
é um recurso interno do pytest que fornece um diretório temporário exclusivo para a função de teste que o solicita. Nós o usamos para criar um arquivo JSON temporário para teste. Osetup_json_file
cria um arquivo temporário com algum conteúdo JSON e retorna o caminho para esse arquivo, que é então usado pelotest_read_json_correctly
função de teste.O
test_file_not_found
testa o comportamento da funçãoJSONReader
ao tentar ler um arquivo inexistente, esperando umFileNotFoundError
seja gerado.Essa configuração garante que os testes sejam isolados e não dependam ou interfiram em arquivos externos, tornando seus testes mais confiáveis e portáteis.
Nessa resposta, o senhor tem um dispositivo de teste que cria um arquivo temporário para salvar o conteúdo da amostra JSON. Em pytest
, o tmp_path
oferece uma maneira rápida de criar diretórios temporários. Não é necessário remover explicitamente o diretório temporário, pois o dispositivo cuida dessa tarefa para você.
A resposta não é perfeita. Em vez de docstrings formais, as funções de teste começam com um comentário, mas isso é um problema de estilo de codificação. Outro detalhe que aparece é que a resposta inclui uma importação desnecessária. O dispositivo e os testes não usam o os
portanto, o senhor pode remover o módulo importaçãoe seu código de teste estará pronto para ser testado. Nesse caso, import pytest
é necessário, pois é usado para definir seu dispositivo.
Veja como executar os testes:
Os testes foram executados com sucesso! Portanto, o dispositivo está funcionando corretamente.
Usando outros tipos de prompts para escrever testes
Até agora, o senhor incluiu o código para o qual deseja escrever testes em cada prompt do ChatGPT. Às vezes, não é possível fazer isso porque o senhor precisa cumprir requisitos de privacidade ou manter o código da sua empresa seguro.
Nesse cenário, o senhor pode criar prompts que usem apenas a assinatura de suas classes, métodos e funções. O senhor também pode usar descrições gerais ou especificações do seu código para desenvolver prompts funcionais.
Observação: Há muitas ações judiciais em andamento sobre o uso de dados pelo ChatGPT. De qualquer forma, o senhor deve verificar o site do ChatGPT termos de uso para ter certeza de que o senhor está usando a ferramenta da maneira correta.
Na seção a seguir, os senhores explorarão exemplos de criação de prompts com assinaturas e descrições.
Incluindo somente assinaturas em seus prompts
Para ilustrar como criar prompts que usam a assinatura de suas classes, métodos e funções, considere a assinatura de uma função que verifica se um número está em um determinado intervalo. Lembre-se de iniciar um novo tópico de bate-papo antes de executar o prompt abaixo:
O senhor: Escreva
pytest
testes para uma função com a seguinte assinatura:ChatGPT:
Para escrever
pytest
testes para a funçãoin_interval(number: int, start: int, end: int) -> bool
, primeiro precisamos definir a função com base em sua assinatura. Essa função deve retornarTrue
senumber
estiver entrestart
eend
(inclusive), eFalse
caso contrário. Vamos definir essa função e, em seguida, escrever váriaspytest
casos de teste para cobrir vários cenários, inclusive casos extremos.Primeiro, aqui está uma implementação simples do
in_interval
:Agora, vamos escrever a função
pytest
. Crie um novo arquivo Python para seus testes, por exemplo,test_in_interval.py
e inclua o seguinte código:Esse arquivo de teste usa
pytest.mark.parametrize
para definir vários casos de teste para oin_interval
. Cada caso de teste especifica umnumber
,start
,end
, e oexpected
resultado. Essa abordagem permite que o senhor teste com eficiência sua função com uma variedade de entradas para garantir que ela se comporte corretamente em diferentes condições.
Neste exemplo, a assinatura da função é o único contexto que o senhor fornece ao ChatGPT. O modelo de linguagem é inteligente o suficiente para examinar o nome e os argumentos da função e gerar uma implementação adequada. Esse pode não ser o caso das funções do mundo real.
Em seguida, o chat gera uma função de teste com oito conjuntos de parâmetros. Cada conjunto de parâmetros testa a função em um cenário específico.
Observe que ter nomes descritivos de funções e argumentos é fundamental nesse tipo de prompt. Adição de dicas de tipo na assinatura da função também melhorará a qualidade da documentação gerada.
Prompts de redação que usam descrições de código
O senhor também pode criar um prompt apenas descrevendo a entrada e a saída do seu código ou fornecendo uma descrição detalhada do que o código faz. Novamente, esses prompts são úteis quando o senhor não tem permissão para carregar o código como parte do prompt.
Para ilustrar, aqui está um prompt que pede ao ChatGPT para escrever testes para uma função que determina se um número inteiro é primo:
O senhor: Escreva
pytest
testes para uma função que recebe um número inteiro como argumento e determina se ele é um número primo.ChatGPT:
Para escrever
pytest
para uma função que determina se um determinado número inteiro é um número primo, primeiro precisamos definir a função. Aqui está uma implementação simples de tal função, que chamaremos deis_prime
. Essa função retornaTrue
se o número for primo, eFalse
caso contrário:Agora, vamos escrever o
pytest
. Crie um novo arquivo Python para seus testes, por exemplo,test_is_prime.py
e inclua o seguinte código:Esse arquivo de teste usa
pytest.mark.parametrize
para especificar vários casos de teste para ois_prime
função. Cada caso de teste fornece umnumber
para testar e oexpected
resultado (Verdadeiro ou Falso). Essa configuração permite que o senhor teste de forma abrangente sua função em relação a uma variedade de entradas, incluindo casos extremos, como o menor número primo, números compostos, o número um, zero e números negativos.
Novamente, o chat gerou uma possível implementação para a função. Depois disso, ele gera os testes. O senhor deve fornecer descrições mais detalhadas para funções, classes ou outras partes de código mais complexas para que o ChatGPT possa gerar respostas melhores.
Também é importante observar que esses testes são apenas um ponto de partida. Cabe ao senhor modificá-los e ajustá-los conforme necessário para corresponder ao seu código específico. De qualquer forma, eles podem evitar que o senhor escreva muito código padrão.
Conclusão
Agora o senhor sabe como aproveitar o poder de ferramentas como o ChatGPT para escrever testes unitários para seu código Python. O senhor usou o LLM para gerar testes usando diferentes ferramentas, incluindo doctest
, unittest
, e pytest
. Nesse processo, o senhor aprendeu a criar casos de teste, dispositivos, conjuntos de teste e muito mais.
Neste tutorial, o senhor aprendeu a:
- Pedir ao ChatGPT para criar testes rápidos usando o
doctest
- Use o ChatGPT para gerar
unittest
testes, instalações e suítes - Crie prompts do ChatGPT para escrever
pytest
Testes e fixtures - Use prompts alternativos para casos em que o código não está disponível
Com essas habilidades, o senhor está pronto para começar a criar baterias de teste robustas e completas para seu código e projetos Python.