1. O Que São Testes Unitários?
Testes unitários são pequenos testes automatizados que verificam se unidades individuais do código (como funções ou métodos) estão funcionando conforme o esperado. O objetivo é garantir que cada unidade de código seja testada de maneira independente, facilitando a detecção de erros e problemas antes que eles se tornem maiores no sistema.
Ao adicionar testes unitários ao seu projeto, você consegue identificar e corrigir erros de maneira mais eficiente, além de garantir que novas alterações no código não quebrem funcionalidades existentes.
2. Usando a Biblioteca unittest
Python vem com uma biblioteca embutida chamada unittest
, que fornece as ferramentas necessárias para criar, organizar e executar testes unitários. Para começar a criar testes, você precisa definir classes de teste que herdam de unittest.TestCase
.
# Exemplo básico de testes unitários com unittest
import unittest
def soma(a, b):
return a + b
class TesteSoma(unittest.TestCase):
def test_soma_positivos(self):
self.assertEqual(soma(3, 4), 7)
def test_soma_negativos(self):
self.assertEqual(soma(-2, -5), -7)
if __name__ == '__main__':
unittest.main()
Neste exemplo, definimos uma função simples soma()
e criamos uma classe de teste TesteSoma
com dois métodos de teste. O método assertEqual()
verifica se o valor retornado pela função é igual ao esperado. Para executar os testes, basta rodar o script e o unittest
processará tudo automaticamente.
3. Estrutura de um Teste
Os testes unitários seguem uma estrutura padrão, dividida em três partes principais:
- Configuração (Setup): Inicializar qualquer dado ou objeto necessário para o teste.
- Ação (Action): Executar a função ou método que está sendo testado.
- Verificação (Assert): Verificar se o resultado obtido é o esperado.
Veja como essa estrutura é aplicada em um exemplo de teste com setup e teardown (limpeza pós-teste):
# Exemplo com setup e teardown
import unittest
class TesteSoma(unittest.TestCase):
def setUp(self):
print("Configurando o teste...")
def tearDown(self):
print("Limpando após o teste...")
def test_soma(self):
resultado = soma(5, 7)
self.assertEqual(resultado, 12)
if __name__ == '__main__':
unittest.main()
O método setUp()
é executado antes de cada teste, e tearDown()
é chamado após cada teste. Eles são úteis para preparar o ambiente de teste, como inicializar objetos ou conexões com o banco de dados, e para limpar recursos usados no teste.
4. Outros Métodos de Verificação
Além de assertEqual()
, o unittest
oferece outros métodos para verificar diferentes tipos de condições nos testes:
assertTrue(x):
Verifica sex
é verdadeiro.assertFalse(x):
Verifica sex
é falso.assertIn(a, b):
Verifica se o valora
está na sequênciab
.assertIsNone(x):
Verifica sex
éNone
.
# Exemplo de verificação com assertTrue e assertIn
def eh_par(num):
return num % 2 == 0
class TesteParidade(unittest.TestCase):
def test_numero_par(self):
self.assertTrue(eh_par(4))
def test_numero_nao_par(self):
self.assertFalse(eh_par(7))
if __name__ == '__main__':
unittest.main()
5. Organizando Testes com Suítes
Conforme o projeto cresce, é importante organizar os testes. O unittest
permite agrupar testes em suítes para que eles possam ser executados juntos. Veja um exemplo de como organizar múltiplos testes em uma suíte:
# Exemplo de uma suíte de testes
import unittest
class TesteSoma(unittest.TestCase):
def test_soma_positivos(self):
self.assertEqual(soma(3, 4), 7)
class TesteParidade(unittest.TestCase):
def test_numero_par(self):
self.assertTrue(eh_par(6))
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(TesteSoma('test_soma_positivos'))
suite.addTest(TesteParidade('test_numero_par'))
runner = unittest.TextTestRunner()
runner.run(suite)
Com as suítes, você pode definir conjuntos específicos de testes que deseja executar, facilitando a organização e o gerenciamento dos testes em projetos maiores.
6. Cobertura de Código com coverage
Além de escrever testes, é importante garantir que a maior parte possível do código seja testada. A ferramenta coverage
ajuda a medir a cobertura de código dos seus testes, mostrando quais partes do código foram testadas e quais não.
# Instalando o coverage
pip install coverage
# Rodando testes e verificando cobertura
coverage run -m unittest
coverage report -m
Com esses comandos, você pode gerar um relatório detalhado mostrando a porcentagem de código coberta pelos testes e identificar as áreas que ainda precisam ser testadas.
Conclusão
Testes unitários são essenciais para garantir a qualidade e a confiabilidade do seu código. Usando a biblioteca unittest
em Python, você pode criar e organizar testes de maneira eficiente, detectar erros precocemente e aumentar a confiança nas alterações de código. À medida que seu projeto cresce, adicionar testes bem estruturados e medir a cobertura de código se torna uma prática fundamental para o desenvolvimento de software de qualidade.