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