{"meta":{"title":"Escrevendo testes com GitHub Copilot","intro":"Use Copilot para gerar testes de unidade e integração e ajudar a melhorar a qualidade do código.","product":"GitHub Copilot","breadcrumbs":[{"href":"/pt/copilot","title":"GitHub Copilot"},{"href":"/pt/copilot/tutorials","title":"Tutoriais"},{"href":"/pt/copilot/tutorials/write-tests","title":"Escrever testes"}],"documentType":"article"},"body":"# Escrevendo testes com GitHub Copilot\n\nUse Copilot para gerar testes de unidade e integração e ajudar a melhorar a qualidade do código.\n\n## Introdução\n\nGitHub Copilot pode ajudá-lo a desenvolver testes rapidamente e melhorar a produtividade. Neste artigo, demonstraremos como você pode usar Copilot para gravar testes de unidade e integração. Embora Copilot tenha um bom desempenho na geração de testes para funções básicas, cenários complexos exigem prompts e estratégias mais detalhados. Este artigo apresentará exemplos práticos de como usar Copilot para dividir tarefas em partes e verificar a correção do código.\n\n## Pré-requisitos\n\nAntes de getting started você deve ter o seguinte:\n\n* Um [GitHub Copilot plano de assinatura](/pt/copilot/get-started/plans).\n* Visual Studio, Visual Studio Code, ou qualquer IDE da JetBrains.\n* A extensão [GitHub Copilot](/pt/copilot/how-tos/set-up/install-copilot-extension) instalada no seu IDE.\n\n## Escrevendo testes de unidade com Copilot Chat\n\nNesta seção, exploraremos como usar GitHub Copilot Chat para gerar testes de unidade para uma classe de Python. Este exemplo demonstra como você pode usar Copilot para criar testes de unidade para uma classe como `BankAccount`. Mostraremos como solicitar Copilot a geração de testes, executá-los e verificar os resultados.\n\n### Exemplo de classe: `BankAccount`\n\nVamos começar com uma classe `BankAccount` que contém métodos para depositar, sacar e obter o saldo de uma conta. Crie um novo arquivo `bank_account.py` em um GitHub repositório e adicione a seguinte `BankAccount` classe em Python.\n\n```python\nclass BankAccount:\n    def __init__(self, initial_balance=0):\n        if initial_balance < 0:\n            raise ValueError(\"Initial balance cannot be negative.\")\n        self.balance = initial_balance\n\n    def deposit(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Deposit amount must be positive.\")\n        self.balance += amount\n\n    def withdraw(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Withdrawal amount must be positive.\")\n        if amount > self.balance:\n            raise ValueError(\"Cannot withdraw more than the current balance.\")\n        self.balance -= amount\n\n    def get_balance(self):\n        return self.balance\n```\n\n### Gerando testes de unidade com Copilot Chat\n\nVocê pode solicitar ao Copilot que escreva testes que abrangem uma variedade de cenários. Seja específico com os requisitos de teste para obter os melhores resultados. Veja a seguir um exemplo de solicitação que você pode usar para gerar testes de unidade para a classe `BankAccount`.\n\n**Solicitação:***Desenvolva um conjunto abrangente de testes de unidade para a função BankAccount() no Python. Escreva vários métodos de teste que abrangem uma ampla gama de cenários, incluindo casos de borda, tratamento de exceção e validação de dados.*\n\nEste comando realiza algumas ações importantes:\n\n* **Escopo:** Solicita explicitamente um conjunto abrangente de testes de unidade, para que Copilot gere mais do que apenas testes básicos, cobrindo uma variedade de casos de uso.\n* **Cenários**: a solicitação especifica que os testes devem incluir:\n  * **Casos extremos**: testes para condições limite (por exemplo, valores negativos para depósitos ou saques, saques acima do saldo disponível).\n  * **Tratamento de exceção**: testa erros que devem ser gerados quando determinadas ações inválidas ocorrem (por exemplo, saques acima do saldo disponível, depósito de valores negativos).\n  * **Validação de dados**: garante que as entradas sejam validadas e tratadas corretamente pelos métodos.\n\nCopilot fornecerá uma resposta semelhante à seguinte.\n\n```python\nimport unittest\nfrom bank_account import BankAccount\n\nclass TestBankAccount(unittest.TestCase):\n    def setUp(self):\n        self.account = BankAccount()\n\n    def test_initial_balance(self):\n        self.assertEqual(self.account.get_balance(), 0)\n\n    def test_deposit_positive_amount(self):\n        self.account.deposit(100)\n        self.assertEqual(self.account.get_balance(), 100)\n\n    def test_withdraw_within_balance(self):\n        self.account.deposit(100)\n        self.account.withdraw(50)\n        self.assertEqual(self.account.get_balance(), 50)\n\n    def test_deposit_negative_amount_raises_error(self):\n        with self.assertRaises(ValueError):\n            self.account.deposit(-100)\n\n    def test_withdraw_negative_amount_raises_error(self):\n        with self.assertRaises(ValueError):\n            self.account.withdraw(-50)\n\n    def test_withdraw_more_than_balance_raises_error(self):\n        self.account.deposit(100)\n        with self.assertRaises(ValueError):\n            self.account.withdraw(200)\n\n    def test_initial_balance_negative_raises_error(self):\n        with self.assertRaises(ValueError):\n            BankAccount(-100)\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\n### Executar os casos de testes\n\nO conjunto de testes gerado por Copilot inclui um caso de teste para cada cenário especificado no prompt. Cada função da classe `BankAccount` é testada em relação a uma variedade de condições, incluindo operações válidas, como depósitos e saques, bem como casos de borda, como valores negativos e tentativas de saque acima do saldo disponível.\n\nDepois de Copilot gerar o conjunto de testes para sua satisfação, adicione o código a um novo arquivo `test_bank_account.py`. Você pode perguntar a ele como executar os testes.\n\n**Prompt:***\"Como executo esses testes de unidade no Python usando o framework unittest?\"*\n\nCopilot fornecerá o seguinte comando bash.\n\n```bash\npython -m unittest test_bank_account.py\n```\n\nDepois de executar os testes, você verá a saída no terminal ou IDE. Se todos os testes forem aprovados, você poderá ter certeza de que a classe `BankAccount` está funcionando conforme o esperado.\n\n#### Comando barra\n\nAlém disso, você pode pedir para Copilot escrever um conjunto completo de testes unitários com o comando de barra `/tests`. Verifique se o arquivo está aberto na guia atual do IDE e Copilot gerará testes de unidade para esse arquivo. Os testes gerados Copilot podem não abranger todos os cenários, portanto, você sempre deve examinar o código gerado e adicionar quaisquer testes adicionais que possam ser necessários.\n\n> \\[!TIP] Se você solicitar Copilot a gravação de testes para um arquivo de código que ainda não esteja coberto por testes de unidade, você poderá fornecer Copilot um contexto útil abrindo um ou mais arquivos de teste existentes em guias adjacentes em seu editor.\n> Copilot será capaz de ver a estrutura de teste que você usa e terá maior probabilidade de gravar um teste que seja consistente com seus testes existentes.\n\nCopilot gerará uma suíte de testes unitários, como o exemplo a seguir.\n\n```python\nimport unittest\nfrom bank_account import BankAccount\n\nclass TestBankAccount(unittest.TestCase):\n    def setUp(self):\n        self.account = BankAccount()\n\n    def test_initial_balance(self):\n        self.assertEqual(self.account.get_balance(), 0)\n```\n\n## Gravando testes de integração com Copilot\n\nOs testes de integração são essenciais para garantir que os vários componentes do sistema funcionem corretamente quando combinados. Nesta seção, vamos estender a classe `BankAccount` para incluir interações com um serviço externo `NotificationSystem` e vamos usar simulações para testar o comportamento do sistema sem precisar de conexões reais. O objetivo dos testes de integração é verificar a interação entre a classe `BankAccount` e os serviços `NotificationSystem`, garantindo que eles trabalhem juntos corretamente.\n\n### Exemplo de classe: `BankAccount` com serviços de notificação\n\nVamos atualizar a classe `BankAccount` para incluir interações com um serviço externo, como um `NotificationSystem` que envia notificações aos usuários. O `NotificationSystem` representa a integração que precisará ser testada.\n\nAtualize a classe `BankAccount` no arquivo `bank_account.py` com o snippet de código a seguir.\n\n```python\nclass BankAccount:\n    def __init__(self, initial_balance=0, notification_system=None):\n        if initial_balance < 0:\n            raise ValueError(\"Initial balance cannot be negative.\")\n        self.balance = initial_balance\n        self.notification_system = notification_system\n\n    def deposit(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Deposit amount must be positive.\")\n        self.balance += amount\n        if self.notification_system:\n            self.notification_system.notify(f\"Deposited {amount}, new balance: {self.balance}\")\n\n    def withdraw(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Withdrawal amount must be positive.\")\n        if amount > self.balance:\n            raise ValueError(\"Cannot withdraw more than the current balance.\")\n        self.balance -= amount\n\n        if self.notification_system:\n            self.notification_system.notify(f\"Withdrew {amount}, new balance: {self.balance}\")\n\n    def get_balance(self):\n        return self.balance\n```\n\nAqui, dividiremos nossa solicitação para que Copilot escreva testes de integração para a classe `BankAccount` em partes menores e mais fáceis de gerenciar. Isso ajudará a Copilot gerar testes mais precisos e relevantes.\n\n**Solicitação:***“Escreva testes de integração para a função `deposit` na classe `BankAccount`. Use simulações para simular o `NotificationSystem` e verificar se ele é chamado corretamente após um depósito”.*\n\nEste comando realiza algumas ações importantes:\n\n* **Escopo**: especifica testes de integração, com foco na interação entre a função `deposit` e o `NotificationSystem`, em vez de apenas testes de unidade.\n* **Simulações**: solicita explicitamente o uso de simulações para simular o `NotificationSystem`, garantindo que a interação com sistemas externos seja testada sem depender da implementação real deles.\n* **Verificação**: a solicitação enfatiza a verificação de que o `NotificationSystem` é chamado corretamente após um depósito, garantindo que a integração entre os componentes funcione conforme o esperado.\n* **Especificidade**: a solicitação indica claramente o método (`deposit`) e a classe (`BankAccount`) a serem testados.\n\n> \\[!TIP] Se Copilot estiver produzindo testes inválidos, forneça exemplos de entradas e saídas para a função que você deseja testar. Isso ajudará a Copilot avaliar o comportamento esperado da função.\n\nCopilot gerará um conjunto de testes como o seguinte.\n\n```python\nimport unittest\nfrom unittest.mock import Mock\nfrom bank_account import BankAccount\n\nclass TestBankAccountIntegration(unittest.TestCase):\n    def setUp(self):\n        self.notification_system = Mock()\n\n    def test_deposit_with_notification(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        account.deposit(50)\n        self.assertEqual(account.get_balance(), 150)\n        self.notification_system.notify.assert_called_once_with(\"Deposited 50, new balance: 150\")\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\nAdicione o código gerado a um novo arquivo `test_bank_account_integration.py`.\n\n### Aprimorar os casos de teste\n\nA solicitação acima gerou um caso de teste individual que verifica se o `NotificationSystem` é chamado quando um depósito válido é feito. No entanto, ela não abrange casos em que um erro é gerado durante o depósito. Nesses cenários, o `NotificationSystem` não deve ser chamado. Precisamos adicionar um caso de teste que trata depósitos inválidos e garantir que o sistema de notificação não seja disparado.\n\n**Solicitação:***“Adicione um caso de teste para valores de depósito inválidos para verificar se a função gera as exceções corretas e se o `NotificationService` não é chamado”.*\n\nCopilot gerará um caso de teste, como o seguinte.\n\n```python\n    def test_deposit_negative_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.deposit(0)\n        self.notification_system.notify.assert_not_called()\n```\n\n### Como perguntar sobre áreas de aprimoramento\n\nAgora que escrevemos os casos de teste para validar a funcionalidade de integração para depósitos, essa é uma ótima oportunidade para procurar aprimoramentos no conjunto de testes. Embora os testes atuais estejam funcionais, podemos solicitar Copilot a avaliação da cobertura de código e sugerir áreas de melhoria.\n\n**Solicitação:***“Quais outros testes devem ser incluídos para garantir a cobertura completa da integração entre a classe `BankAccount` e o `NotificationSystem`?”*\n\nFazer essa pergunta ao Copilot pode ajudar você a identificar casos de teste ausentes que podem ter sido negligenciados.\nNessa situação, embora tenhamos testado depósitos válidos e inválidos, ainda não abordamos a funcionalidade de saques.\n\nCopilot gerará um conjunto de testes atualizado, como o seguinte.\n\n<details>\n  <summary>Clique aqui para expandir o exemplo de código gerado completo</summary>\n\n```python\nimport unittest\nfrom unittest.mock import Mock\nfrom bank_account import BankAccount\n\nclass TestBankAccountIntegration(unittest.TestCase):\n    def setUp(self):\n        self.notification_system = Mock()\n\n    def test_deposit_with_notification(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        account.deposit(50)\n        self.assertEqual(account.get_balance(), 150)\n        self.notification_system.notify.assert_called_once_with(\"Deposited 50, new balance: 150\")\n\n    def test_deposit_negative_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.deposit(-50)\n        self.notification_system.notify.assert_not_called()\n\n    def test_deposit_zero_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.deposit(0)\n        self.notification_system.notify.assert_not_called()\n\n    def test_withdraw_with_notification(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        account.withdraw(30)\n        self.assertEqual(account.get_balance(), 70)\n        self.notification_system.notify.assert_called_once_with(\"Withdrew 30, new balance: 70\")\n\n    def test_withdraw_exceeding_balance_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.withdraw(150)\n        self.notification_system.notify.assert_not_called()\n\n    def test_withdraw_negative_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.withdraw(-30)\n        self.notification_system.notify.assert_not_called()\n\n    def test_withdraw_zero_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.withdraw(0)\n        self.notification_system.notify.assert_not_called()\n\n    def test_initial_negative_balance_raises_error(self):\n        with self.assertRaises(ValueError):\n            BankAccount(initial_balance=-100, notification_system=self.notification_system)\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\n</details>\n\nDepois que o Copilot tiver gerado o conjunto de testes desejado, execute os testes com o comando abaixo para verificar os resultados.\n\n```bash\npython -m unittest test_bank_account_integration.py\n```\n\n## Usar Copilot Spaces para melhorar as sugestões de teste\n\nCopilot Spaces é um recurso que permite organizar e compartilhar o contexto específico da tarefa com Copilot. Isso pode ajudar a aumentar a relevância das sugestões recebidas. Ao fornecer Copilot mais contexto sobre seu projeto, você pode obter melhores sugestões de teste.\n\nPor exemplo, você pode criar um espaço que inclua:\n\n* O módulo que você está testando (como `payments.js`)\n* O conjunto de testes atual (como `payments.test.js`)\n* Um relatório de cobertura de teste ou anotações sobre o que está faltando\n\nNesse espaço, você pode fazer perguntas Copilot como:\n\n> Quais casos de teste estão faltando no `payments.test.js` de acordo com a lógica em `payments.js`?\n\nOu:\n\n> Escreva um teste unitário para a lógica de reembolso em `refund.js`, seguindo a estrutura do conjunto de testes existente.\n\nPara obter mais informações sobre como usar Copilot Spaces, consulte [Sobre o GitHub Copilot Spaces](/pt/copilot/concepts/context/spaces)."}