E retire os resultados do teste fora do código. Este artigo é sobre automação e aumenta a conveniência dos testes em Python.

Introdutório
Eu tive um projeto que está em desenvolvimento há vários anos. Não houve testes no projeto. E ele também tinha dependências ativas de outras equipes, o que também influenciou o resultado.
O teste de regressão foi uma das etapas para um desenvolvimento mais confiante. Sua essência está na comparação dos dados calculados com o último resultado canonizado do programa.
python . .
:
- . , Python xml, json . ,
textwrap.dedent
. - . .
- . , . . .
, . testoot 3.4+.
. .
foo
. :
def foo():
return {'a': 1}
def test_simple(testoot: Testoot):
testoot.test(foo())
pytest
:
pytest -s tests
. . testoot Testoot .
:
def foo():
return {'a': 2}
def test_simple(testoot: Testoot):
testoot.test(foo())
AssertionError
:
...
def test_simple(testoot: Testoot):
> testoot.test(foo()))
cls = <class 'testoot.ext.pytest.PytestComparator'>, test_obj = {'a': 2}, canon_obj = {'a': 1}
@classmethod
def compare(cls, test_obj: any, canon_obj: any):
"""Compares objects"""
> assert test_obj == canon_obj
E AssertionError
. - .
--canonize
.
pytest -s tests --canonize
, pytest ( --verbose ):
tests/test_console/test_console.py [tests/test_console/test_console.py::test_simple]
{'a': 2} == {'a': 1}
~Differing items:
~{'a': 2} != {'a': 1}
~Use -v to get the full diff
Canonize [yn]? y
.
. .
. :
- pickle. Python. VCS pickle
- bytes. , .
- str. utf-8 , .
- json . json, , .
, VCS .
. .
def test_filename(testoot: Testoot):
d = Path(testoot.storage.root_dir / 'hello.json')
d.write_text('{}')
testoot.test_filename(str(d))
Testoot. :
import pytest
from testoot.ext.pytest import PytestContext
from testoot.ext.simple import DefaultBaseTestoot
from testoot.pub import AskCanonizePolicy, PickleSerializer, \
LocalDirectoryStorage, ConsoleUserInteraction, Testoot
@pytest.fixture(scope='module')
def base_testoot():
regress = DefaultBaseTestoot(
storage=LocalDirectoryStorage('.testoot'),
)
regress.storage.ensure_exists()
yield regress
@pytest.fixture(scope='function')
def testoot(base_testoot, request):
fixture = Testoot(base_testoot, PytestContext(request))
yield fixture
DefaultBaseTestoot . Testoot (scope='function'). pytest request , .
DefaultBaseTestoot BaseTestoot -: .testoot pickle-, --canonize
.
-:
regress = DefaultBaseTestoot(
serializer=JsonSerializer(),
)
. pytest :
class PytestComparator(Comparator):
@classmethod
def compare(cls, test_obj: any, canon_obj: any):
"""Compares objects"""
assert test_obj == canon_obj
PytestContext(request, serializer=BinarySerializer(), comparator=PytestComparator())
. :
def test_str(testoot: Testoot):
result = 'abc'
regress.test(result, serializer=StringSerializer(), comparator=PytestComparator())
, BaseTestoot.
, . , .
Também pode ser necessário remover elementos constantemente alterados dos dados, como a data da última alteração. Para que essas alterações não penetrem nos dados armazenados.
Conclusão
Esta foi uma visão geral dos testes e recursos da biblioteca para Python. Ficarei feliz em comentários e sugestões!
Instalação: pip3 install testoot
Documentação: https://testoot.readthedocs.io
Código fonte: https://github.com/aptakhin/testoot