TDD e Python 3: iniciando com uma aplicação

“Obey the Testing Goat! Do Nothing Until You Have a Test”

Sabe-se que Python é uma das linguagens mais faladas pelo mundo [1], sobretudo pela versatilidade dela em diversos ramos de aplicação como ciência de dados, programação web, entre outras. Além disso, ela é extremamente amigável aos usuários. Isso porque o seu autor, Guido von Rossum, antes de Python trabalhou na linguagem ABC, que tinha o intuito de ensinar alguém não versado em programação.

Com a finalidade de ampliar meus conhecimentos comprei uma coleção da O’Reilly sobre Python. Um livro em particular me chamou muito a atenção. Em Test Driven Development [2] o autor cria uma aplicação do zero utilizando testes. Achei muito interessante a abordagem dele. Para reforçar o aprendizado e contribuir com a comunidade vou criar uma aplicação usando TDD e Python 3, repassando os conceitos que mais chamaram a minha atenção neste livro. Sem mais delongas, vamos iniciar descrevendo os requisitos de nossa aplicação!

Requisitos

A primeira coisa que devemos instalar é o Python 3. Se você utiliza um sistema baseado em Unix, assim como eu, já deve possuí-lo por padrão. Se não for o caso basta ir em https://www.python.org/ e baixar o Python 3 recomendado ao seu sistema operacional.

Agora um parênteses para os programadores javascript, assim como eu. Quando desenvolvemos usando NodeJS, o npm instala por padrão as dependências de forma local, dentro do node_modules. Ele apenas instalará de forma global se o usuário assim o especificar. Em Python acontece o contrário. Se nada for dito, o PIP (Python Package Index) instalará de forma global as dependências. No entanto, é interessante termos um ambiente separado para nossa aplicação, deixando o que é utilizado pelo sistema operacional em paz, até porque diferentes projetos podem utilizar diferentes versões de dependência. Para tanto utilizaremos o virtualenv, assim isolamos as dependências de cada projeto e do sistema operacional.

Para instalá-lo, basta utilizar o seguinte comando:

Com o virtualenv instalado caminhamos até o diretório do projeto e criamos um ambiente virtual para nossa aplicação:

Maravilha! A pasta venv vai funcionar como se fosse o nosso node_modules.

Se quiser desativar o ambiente virtual em algum momento no seu terminal use o comando deactivate ou apenas o encerre. Também já iniciamos nosso repositório no git e adicionamos o .gitignore. Eu usei uma ferramenta on-line para gerar o gitignore, você pode encontrar a minha versão aqui: https://www.toptal.com/developers/gitignore/api/python,virtualenv,django

Agora faça o download do Firefox mais recente em https://www.mozilla.org/pt-BR/firefox/new/ e o geckodriver em https://github.com/mozilla/geckodriver/releases. Este último você deve extrair  o arquivo tar.gz em /usr/local/bin.

Ok! Uma vez tendo tudo instalado estamos prontos para começar!

Um pouco de teoria

Quando falamos em Test Driven Development, ou seja, Desenvolvimento Orientado a Testes, estamos falando de uma maneira de se desenvolver software. Esse método de programar obedece algumas etapas, que podemos resumir em:

  1. Obedeça o bode de teste, sempre escreva um teste antes: em TDD sempre buscamos escrever os testes primeiro. Dessa forma, na primeira vez que o chamarmos ele deve falhar. Detalhe: o bode é o mascote da comunidade, portanto sempre o obedeça!
  2. Rode o teste e faça-o falhar
  3. Escreva o código que entrega os requisitos solicitados pelo teste
  4. Rode o teste
  5. Repita o processo.

Esse método de programar geralmente é recomendado como boas práticas praticamente em qualquer projeto. Isso porque todo código testado é um código certamente mais limpo que códigos não testados, mas isso tem um custo no curto prazo. Se for um projeto de longo prazo esse custo acaba se pagando, pois teremos menos retrabalho. Ainda assim, quando não temos os requisitos do projeto bem definido, como acontece em uma prova de conceito (POC) por exemplo, desenvolver usando TDD passa a não ser recomendado, até porque o que foi desenvolvido na POC muitas vezes é reescrito completamente antes de virar um produto mínimo viável.

[rock-convert-cta id=”9981″]

Dos Requisitos

Agora vamos definir direitinho que aplicação vamos produzir. Essa é uma parte muito importante, pois como já foi falado quando se usa TDD todos os requisitos devem estar muito bem estabelecidos.

Como tá todo mundo de home office vamos criar um serviço para cadastro de atividades em um quadro. Cada atividade tem um código, um nome, uma descrição, a quantidade de esforço em horas, o autor, o envolvido, uma data e um estado. Também são entidades do nosso banco os usuários, que terão nome e código, e os estados do kanban.

Vamos usar o django 3 e a vantagem de trabalhar com este framework é que ele possui tudo que precisamos para testar nossa aplicação. Não é intuito deste tutorial ser minimalista quanto a criação do projeto, até porque o tutorial do django [3] cumpre muito bem esse papel. Ainda assim faremos uma cobertura básica, para não parecer que as coisas surgiram “do nada”.

Da aplicação

Vamos iniciar nosso projeto! A primeira coisa que termos é um localhost uma aplicação django rodando em localhost. Mas não podemos começar desse ponto porque nossa abordagem não permite, primeiro temos que criar um teste e fazê-lo falhar. Vou separar os testes de integração, unitários e end-to-end. Agora é a hora do bode brilhar, “não faça nada até você ter um teste”.

Em kanban/functional_tests/tests.py definimos o nosso primeiro teste:

Neste teste foi utilizado o test runner do próprio django e o selenium. A classe StaticLiveServerTestCase já lança um servidor em background. Temos dois métodos especiais: setUpClass e tearDownClass, eles são respectivamente chamados na criação e na destruição do objeto. Bora testar:

Ops! Obviamente não temos o projeto iniciado, vamos fazer isso agora para que o nosso teste passe.

Um projeto em django é uma pasta com arquivos de configurações e um app é onde as coisas acontecem de verdade, como consulta em banco, entre outras tarefas. Você pode ter inúmeros apps dentro de um projeto. Dado que vamos usar o test runner do próprio django, temos que refatorar o nosso arquivo de teste, retirando o if __name__ == “__main__”.

Bora rodar os testes de novo:

Funcionou! O ciclo que acabamos de passar se chama red, green, refactor. Basicamente você escreve um teste, faz ele falhar e refatora seu código o mínimo possível para que seu teste passe.

Nosso projeto será feito com graphql, portanto precisamos testar alguma query básica, segue o teste:

Sempre lembrar de definir as variáveis globais GRAPHQL_SCHEMA e GRAPHQL_URL! Repare que este teste irá falhar, porque não definimos a rota do graphql ainda.

Precisamos configurar o graphene para que funcione. Modifique o kanban/settings.py.

E criamos um schema mínimo:

Adicionamos um nosso graphql no urls.py:

Rodamos o teste novamente!

E finalmente damos commit no nosso setup inicial.

Finalmente! Agora devemos ter nossa rota http://127.0.0.1:8000/graphql funcionado bonitão. O schema definido acima é o mais simples possível e tem apenas uma query (hello). Nesse ponto os testes já passam, estamos no fluxo:

  1. Escreva o teste
  2. Faça falhar
  3. Refatore para que o teste passe

Que também é conhecido como red, green, refactor e é uma das bases para o TDD.

Para finalizar as explicações, vamos considerar um último teste unitário.

Esse teste, na verdade, não é unitário. Digo isso porque entende-se como teste unitário como aquele que testa a unidade e ele está fugindo do seu escopo: ele está chegando até o banco. Rodando o teste, ele vai falhar como esperado!

Precisamos definir o nosso model de atividades com pelo menos nome, descrição e data de término.

Precisamos rodar as migrations para que a tabela seja criada no banco, como se segue:

Agora todos os testes passam:

Feito! Dessa maneira vamos seguindo o fluxo e nossa aplicação vai evoluir. Os passos que segui até aqui são os básicos para trabalhar com TDD, Python 3, Django e GraphQL.

Considerações finais

Neste artigo busquei ensinar um pouco sobre os conceitos de test driven development (TDD). No texto apresentei somente três testes, que fazem parte do pontapé inicial da nossa aplicação, porque acho que não faz sentido copiar e colar código aqui. O código será disponibilizado no github, em https://github.com/rbentivenha/kanban, se você tiver interesse em estudar toda a aplicação.

Acompanhe nosso blog para aprender mais sobre desenvolvimento! E para conferir outros conteúdos sobre diversas tecnologias, basta clicar aqui.

Referências

[1] https://www.tiobe.com/tiobe-index/

[2] https://www.oreilly.com/library/view/test-driven-development-with/9781491958698/

[3] https://docs.djangoproject.com/en/3.1/intro/tutorial01/

[4]https://docs.djangoproject.com/en/3.1/topics/testing/tools/#django.test.LiveServerTestCase

Compartilhar:

Rafael
Último artigo
Entrevista técnica: Conheça os tipos para você aplicar no seu processo seletivo
Próximo artigo
Como se tornar um CTO acima da média?