Primeiros passos com testes unitários em Python
Se você precisa escrever teste de unidades em Python e não sabe por onde começar, este artigo é para você!
Em Python, quando queremos escrever testes unitários podemos lançar mãos desde um simples assert, passando por funções
auxiliares até um framework de testes unitários completo. Neste artigo vou mostrar rapidamente como funciona o statement
assert e mostrar também algumas funções que também podem ser úteis, termino mostrando um “Hello world” do
Unit testing framework.
assert
Em Python podemos fazer simples asserções utilizando o statement assert.
assert True
Se executarmos no terminal assert True, o comando fica em silêncio, nada responde. Esse é o comportamento esperado,
pois a asserção teve sucesso e o “silêncio” é o sintoma de que tudo está funcionando.
Se executarmos assert False o comando dispara um erro…
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
O statement aceita como segundo parâmetro uma string que pode ser um mensagem explicativa e é exibida quando a asserção falha.
>>> assert False, "mensagem explicativa"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: mensagem explicativa
Para exemplificar o funcionamento do statement, veja o trecho de código abaixo.
b = 150
expressao = 100 > b
mensagem = "100 deve ser maior que 'b'"
assert expressao, mensagem
Obtemos como como resposta…
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: 100 deve ser maior que b
O que vem depois ?
Se ao invés do “assert”, você quisesse utilizar uma função, por exemplo, test() para realizar pequenos testes, como
seria a implementação dessa função?
Que tal o exemplo abaixo?
def test(expression1, expression2):
if expression1 == expression2:
return 'Pass'
else:
return 'Fail'
Já o tutorial do Google sugere uma função igualmente simples, porém, ligeiramente mais sofisticada, veja código seguinte.
def test(got, expected):
if got == expected:
prefix = ' OK '
else:
prefix = ' X '
print("%s got: %s expected: %s" % (prefix, repr(got), repr(expected)))
Pesquisando na web encontrei mais dois exemplos que merecem nossa atenção.
O primeiro deles, você confere no código abaixo. Repare que temos a utilização do objeto sys e que a saída dessa função é bem mais elaborada, ela alerta até o número da linha onde o erro foi encontrado.
import sys
def test(did_pass):
""" Print the result of a test. """
linenum = sys._getframe(1).f_lineno # Get the caller's line number.
if did_pass:
msg = "Test at line {0} ok.".format(linenum)
else:
msg = ("Test at line {0} FAILED.".format(linenum))
print(msg)
O segundo exemplo é muito parecido com o anterior, até parece que o autor se baseou no primeiro exemplo e implementou sua própria customização. Pequenos detalhes foram alterados.
def test(actual, expected):
import sys
linenum = sys._getframe(1).f_lineno # get the caller's line number.
if (expected == actual):
msg = "Test on line {0} passed.".format(linenum)
else:
msg = ("Test on line {0} failed. Expected '{1}', but got '{2}'."
. format(linenum, expected, actual))
print(msg)
Aí você percebe que precisa de um framework de verdade para escrever seus testes unitários…
Unit Testing Framework
O Unit Testing Framework pode ser o que você esteja procurando.
Longe de querer se aprofundar no framework (leia a documentação), vou apenas mostrar dois exemplos do tipo “Hello world”.
Abaixo um exemplo demonstrando como testar uma simples função.
import unittest
def fun(x):
return x + 1
class MyTest(unittest.TestCase):
def test(self):
self.assertEqual(fun(3), 4)
if __name__ == '__main__':
unittest.main()
O resultado de python foo.py você confere abaixo.
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
O exemplo seguinte demonstra como testar uma pequena classe.
import unittest
class MyFun:
def fun(self, n):
return n + 1
class MyFunTest(unittest.TestCase):
def testFun(self):
obj = MyFun()
self.assertEqual(obj.fun(3), 4)
if __name__ == '__main__':
unittest.main()
O resultado é semelhante ao anterior.
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK