Testes de unidade Python: início rápido

Uma tradução do artigo foi preparada especificamente para os alunos do curso Python QA Engineer .


O teste do código de unidade é parte integrante do ciclo de vida de desenvolvimento de software. Os testes de unidade também formam a base para a realização de testes de regressão, ou seja, garantem que o sistema se comporte de acordo com o cenário em que novos recursos são adicionados ou os existentes são alterados.

Neste artigo, demonstrarei a idéia básica de teste de unidade em uma classe. Na prática, você terá que escrever muitos casos de teste, adicioná-los ao conjunto de testes e executá-los todos juntos. O gerenciamento de casos de teste será discutido no próximo artigo.

Hoje vamos nos concentrar em testar o back-end. Ou seja, o desenvolvedor implementou algum projeto de acordo com as especificações (por exemplo, Calculator.py) e sua tarefa é garantir que o código desenvolvido realmente os corresponda (por exemplo, usando TestCalculator.py ).

Suponha que você tenha escrito a classe Calculadora para executar funções computacionais básicas: adição, subtração, multiplicação e divisão.

O código para isso está aqui ( Calculator.py ):

 #A simple calculator class Calculator: #empty constructor def __init__(self): pass #add method - given two numbers, return the addition def add(self, x1, x2): return x1 + x2 #multiply method - given two numbers, return the #multiplication of the two def multiply(self, x1, x2): return x1 * x2 #subtract method - given two numbers, return the value #of first value minus the second def subtract(self, x1, x2): return x1 - x2 #divide method - given two numbers, return the value #of first value divided by the second def divide(self, x1, x2): if x2 != 0: return x1/x2 

Agora, quero executar um teste de unidade para entender que a funcionalidade na classe acima funciona como planejado.

O Python geralmente vem com o pacote mais unittest . Se não estiver no seu sistema, use o pip para instalá-lo.

O teste de unidade tem a seguinte estrutura:



setUp() e tearDown() são métodos padrão que acompanham a estrutura unittest (eles são definidos na classe unittest.TestCase). Dependendo do seu caso de teste, você pode substituir ou não substituir esses dois métodos por padrão.

É hora de olhar para o código do caso de teste. Aqui está o arquivo TestCalculator.py .

 import unittest from Calculator import Calculator #Test cases to test Calulator methods #You always create a child class derived from unittest.TestCase class TestCalculator(unittest.TestCase): #setUp method is overridden from the parent class TestCase def setUp(self): self.calculator = Calculator() #Each test method starts with the keyword test_ def test_add(self): self.assertEqual(self.calculator.add(4,7), 11) def test_subtract(self): self.assertEqual(self.calculator.subtract(10,5), 5) def test_multiply(self): self.assertEqual(self.calculator.multiply(3,7), 21) def test_divide(self): self.assertEqual(self.calculator.divide(10,2), 5) # Executing the tests in the above test case class if __name__ == "__main__": unittest.main() 

Embora isso não seja necessário, mas como regra chamo a classe de teste com o prefixo Test (no nosso caso TestCalculator). Um requisito chave nesta classe é a presença da superclasse unittest.TestCase .

Sempre que esse caso de teste é executado, o método setUp () é executado primeiro. No nosso caso, simplesmente criamos um objeto da classe Calculator e o salvamos como um atributo da classe. Existem vários outros métodos padrão na classe pai, que discutiremos mais adiante.

Por enquanto, tudo o que você fará é escrever métodos test_xxx para testar cada método na classe Calculadora. Observe que todos os métodos de teste começam com o prefixo test_ . Isso informa ao Python, usando a estrutura mais unida, que esses são métodos de teste.

Em cada um dos métodos de teste, usei o método assertEqual para verificar se os métodos da calculadora retornam o valor esperado. Se o valor de retorno for igual ao valor esperado, o teste será bem-sucedido, caso contrário, falhará.

Existem muitos métodos de assert internos sobre os quais falaremos mais adiante.

A última linha no código acima apenas inicia o caso de teste TestCalculator . Ele executa cada método de teste definido dentro da classe e retorna o resultado.

 python TestCalculator.py -v 


Você verá uma conclusão semelhante à seguinte:

 test_add (__main__.TestCalculator) ... ok test_divide (__main__.TestCalculator) ... ok test_multiply (__main__.TestCalculator) ... ok test_subtract (__main__.TestCalculator) ... ok -------------------------------------------------------------------- Ran 4 tests in 0.000s OK 

E se algo não funcionar como o esperado? Vamos alterar o valor esperado de test_divide de 5 para 6 (5 é o valor correto, agora veremos o que acontece se falhar. Isso não é um erro no código-fonte, mas um erro no conjunto de testes, você também pode ter erros nos conjuntos de testes, portanto, sempre verifique scripts de teste para erros!)

 import unittest from Calculator import Calculator #Test cases to test Calulator methods #You always create a child class derived from unittest.TestCase class class TestCalculator(unittest.TestCase): #setUp method overridden from the parent class TestCase def setUp(self): self.calculator = Calculator() ... def test_divide(self): self.assertEqual(self.calculator.divide(10,2), 6) # Executing the tests in the above test case class if __name__ == "__main__": unittest.main() 

Ao executar este caso de teste, você obterá o seguinte resultado:

 test_add (__main__.TestCalculator) ... ok test_divide (__main__.TestCalculator) ... FAIL test_multiply (__main__.TestCalculator) ... ok test_subtract (__main__.TestCalculator) ... ok ==================================================================== FAIL: test_divide (__main__.TestCalculator) -------------------------------------------------------------------- Traceback (most recent call last): File "TestCalculator.py", line 23, in test_divide self.assertEqual(self.calculator.divide(10,2), 6) AssertionError: 5.0 != 6 -------------------------------------------------------------------- Ran 4 tests in 0.001s FAILED (failures=1) 

Diz aqui que 3 de 4 testes foram bem-sucedidos, mas um falhou. Em um cenário real, supõe-se que seu caso de teste esteja correto, ou seja, dessa forma, ajuda a identificar uma função que não foi implementada corretamente.

Source: https://habr.com/ru/post/pt481806/


All Articles