O Django 2.0 foi lançado,
e com ele o suporte a Python 2.7
deixa de existir para
as próximas versões do framework. Alegria para os usuários, preocupação para os desenvolvedores
dos apps.
Afinal, a versão 1.11
é LTS (Long Term Support), logo, alguns apps (ainda) não podem abraçar
incondicionalmente a versão 3.x
da linguagem.
É nesse cenário que bibliotecas como o six e tox mostram o seu valor. Nesse artigo, vamos falar um pouquinho mais sobre a última.
O Python 2 estará aí por mais um tempo (até 2020). Portanto, qual a motivação para mudar para o Python 3 agora?
Na Loadsmart, o nosso principal projeto é em Python 2.7
.
Mas estamos experimentando Python 3.x
há um bom tempo em projetos paralelos. O fato é que a nova versão da linguagem está mais eficiente,
possui suporte a assincronicidade, melhor controle de exceções e o fogo ardente do "unicode hell" foi controlado.
É verdade que há quebra de compatibilidade entre as versões, mas se considerarmos que a 2.7
só tem mais 2 anos de "vida",
a urgência de migração fica mais latente.
O site oficial da biblioteca a define como:
(...) a generic virtualenv management and test command line tool (...)
Com tox é possível:
Não é só por usar ambientes virtuais que o tox é
uma boa ideia. Ele vem sendo uma mão na roda para os desenvolvedores de pacotes Python
que precisam dar suporte às versões 2.x
e 3.x
, e que utilizam testes automatizados como
design das soluções.
Com o Django a "granularidade" pode ser ainda maior, rodando testes em ambientes que são combinações entre diferentes versões da linguagem e do framework.
Se você estiver utilizando o Travis CI, poderoso serviço de Continuous Integration, consegue reproduzir o comportamento que apresentaremos a seguir através do uso de Build Matrix.
A diferença é que com o tox, podemos obter o mesmo comportamento em tempo de desenvolvimento. Agilizando um pouco mais o processo.
Veja mais em "Travis CI for Python project".
Vou aproveitar o tema e usar o tox para me ajudar em um refactoring de um app de código aberto, que há muito não dou suporte: O django-simple-contact.
Se você quiser acompanhar o passo-a-passo, clone o projeto e dê um git checkout
da revisão 80145ae
:
$ git clone git@github.com:kplaube/django-simple-contact.git
$ cd django-simple-contact/
$ git checkout 80145ae
Na estrutura atual, é possível executar os testes através do setup.py
ou python runtests.py
:
$ python setup.py test
(...)
-----------------------------------------------
Ran 6 tests in 0.230s
OK
Destroying test database for alias 'default'...
É possível fazer a troca da versão do Python/Django de forma manual (através do pyenv, por exemplo). Obviamente que o tox deixa tudo mais interessante (e automatizado).
Finalmente, vamos adicionar a ferramenta ao projeto:
$ pip install tox
Caso esteja usando pyenv, a instalação do tox-pyenv
é sugerida.
Leia mais sobre a biblioteca.
Para deixar tudo mais organizado, vamos nos inspirar na estrutura do projeto
modelmommy. Criaremos um arquivo requirements.txt
com o seguinte conteúdo:
# requirements.txt
bleach
django>=1.8.0
A versão 1.8.0
(até o momento) é a LTS mais antiga, portanto, garantiremos suporte dessa versão em diante.
O bleach é uma dependência do projeto, não
relevante ao exemplo desse artigo.
É interessante deixarmos explícito a instalação do tox... um requirements-dev.txt
pode ser uma solução:
# requirements-dev.txt
tox
Agora, quando um dev juntar-se ao projeto, ele poderá executar o comando pip install -r requirements-dev.txt
, e ter
as dependências necessárias para contribuir com o app.
Antes de executar a ferramenta é necessário criar um arquivo tox.ini
, que será responsável por configurar os ambientes
e disparar os testes:
# tox.ini
[tox]
envlist = py27-django{18,111}, py36-django{18,111,20}
[testenv]
commands = python runtests.py
setenv =
DJANGO_SETTINGS_MODULE=simple_contact.tests.test_settings
PYTHONPATH={toxinidir}
basepython =
py27: python2.7
py36: python3.6
deps =
bleach
django18: Django==1.8
django111: Django==1.11
django20: Django==2.0
Por partes:
[tox]
: Aqui colocamos as configurações globais. envlist
conterá a lista de ambientes nos quais executaremos os testes.[testenv]
: Configurações por ambiente de teste. Poderíamos ter configurações específicas ao utilizar [testenv:py36-django20]
, por exemplo.
commands
: O comando a ser executado.setenv
: Variáveis de ambiente setadas para a execução dos testes.basepython
: Nome do interpretador Python utilizado para a criação do ambiente virtual. Repare no "match" com py27-
e py36-
do envlist
.deps
: Dependências para determinado ambiente de teste. Repare no "match" com django{18,111,20}
.Com o uso dos brackets, ao invés de criarmos um testenv
para cada combinação (exemplo: py27-django18
, py27-django111
, py36-django18
, etc),
o tox fica responsável por fazer a "matriz de combinações".
Agora sim, podemos executar a ferramenta de linha de comando:
$ tox
(...)
ERROR: py27-django18: commands failed
ERROR: py27-django111: commands failed
ERROR: py36-django18: commands failed
ERROR: py36-django111: commands failed
py36-django20: commands succeeded
No meu ambiente local, como esperado, apenas os testes do ambiente py36-django20
passaram. Para ter acesso a versão corrigida,
dê um checkout da revisão a37ebd1608
:
$ git checkout a37ebd1608
$ tox
(...)
py27-django18: commands succeeded
py27-django111: commands succeeded
py36-django18: commands succeeded
py36-django111: commands succeeded
py36-django20: commands succeeded
Perfeito!
Ainda é possível executar apenas os testes de um ambiente específico:
$ tox -e py36-django20
(...)
-----------------------------------------------
Ran 6 tests in 0.055s
OK
Destroying test database for alias 'default'...
O resultado final está disponível na tag 0.3.0
do projeto.
Que esse movimento da comunidade Django consiga influenciar ainda mais a adoção do Python 3. Admito que sem essa "motivação extra", dificilmente cogitaria o upgrade da linguagem em meus projetos nesse momento.
O tox é sem dúvida uma ferramenta que pode auxiliar nessa fase de transição, portanto, não hesite em adicioná-la ao seu toolbelt.
Para uma integração seamless com o Travis CI, o tox-travis é recomendado.
Até a próxima!