Usando strings e doctest
em Python2 e Python3 simultaneamente.
Usando strings de uma forma que funciona tanto no Python2 como no Python3, especialmente quando fazendo testes com doctest
.
Usando doctest
É muito simples, pois na própria docstring de sua função você já escreve os testes. Por exemplo:
# encoding: utf-8
def dobro(x):
"""Retorna o dobro do número passado como argumento
>>> dobro(2)
4
>>> dobro(0)
0
>>> dobro(1.5)
3.0
>>> dobro(-2)
-4
"""
return (x*2)
if __name__ == '__main__':
import doctest
doctest.testmod(verbose=True)
Esse exemplo funciona tanto em Python2 (por isso o encoding
na primeira linha) como no Python3. Salvando como /tmp/test1.py
:
$ python /tmp/a.py
Trying:
dobro(2)
Expecting:
4
ok
Trying:
dobro(0)
Expecting:
0
ok
Trying:
dobro(1.5)
Expecting:
3.0
ok
Trying:
dobro(-2)
Expecting:
-4
ok
1 items had no tests:
__main__
1 items passed all tests:
4 tests in __main__.dobro
4 tests in 2 items.
4 passed and 0 failed.
Test passed.
Tente executar também python3 /tmp/teste1.py
. A saída deve ser a mesma.
Maravilhoso! Meu problema veio quando tive que fazer testes com funções que retornavam strings.
# encoding: utf-8
import doctest
def cumprimenta(fulano):
"""Cumprimenta com "Olá, Fulano!". Se fulano for vazio retorna "Olá."
>>> cumprimenta('')
'Olá.'
>>> cumprimenta('Paulo')
'Olá, Paulo!'
"""
return 'Olá, %s!'%fulano if fulano else 'Olá.'
doctest.testmod()
Com PY2 temos essa saída:
$ python2 /tmp/test2.py
**********************************************************************
File "/tmp/test2.py", line 8, in __main__.cumprimenta
Failed example:
cumprimenta('')
Expected:
'Olá.'
Got:
'Ol\xc3\xa1.'
**********************************************************************
File "/tmp/test2.py", line 10, in __main__.cumprimenta
Failed example:
cumprimenta('Paulo')
Expected:
'Olá, Paulo!'
Got:
'Ol\xc3\xa1, Paulo!'
**********************************************************************
1 items had failures:
2 of 2 in __main__.cumprimenta
***Test Failed*** 2 failures.
Com PY3 temos essa:
$ python3 /tmp/test2.py
$
Ou seja, tudo certo.
Aqui entramos no terrível mundo das codificações de caracteres em PY2. Nem vou mostrar o que tentei, pois é ridículo. Pesquisando com mais calma achei essa questão no StackOverflow:
http://stackoverflow.com/questions/1733414/how-do-i-include-unicode-strings-in-python-doctests
Moleza! E agora? Testemos isso:
# encoding: utf-8
from __future__ import print_function
import doctest
def cumprimenta(fulano):
"""Cumprimenta com "Olá, Fulano!". Se fulano for vazio retorna "Olá."
>>> print(cumprimenta(''))
Olá.
>>> print(cumprimenta('Paulo'))
Olá, Paulo!
"""
return 'Olá, %s!'%fulano if fulano else 'Olá.'
doctest.testmod()
Adicionamos o modulo future para que o print
seja uma função no PY2.