Test Driven Development

Muitas vagas, pelo menos das empresas que se respeitam, exigem TDD na lista de habilidades dos candidatos. A motivacao sao os resultados que o TDD entrega afinal os leads entendem que o maior custo de um projeto é o desenvolvimento a longo prazo nao o desenvolvimento inicial e sabem que o TDD mantem a base de codigo limpa a longo prazo. 

Os tech leads estao corretos de pedir (exigir?) que os candidatos saibam desenvolver com TDD, mas apesar disso poucos desenvolvedores sabem a pratica e a teoria do TDD. Nessa serie de posts e videos vamos discutir a teoria, a pratica e criticas ao TDD com foco em sistemas embarcados. O resultado dos videos pode ser utilizado como portifolio no seu Github para potenciais empregadores.


TDD significa Test Driven Development (Desenvolvimento Guiado por Testes em portugues), é uma disciplina de desenvolvimento de software onde desenvolve-se os testes antes de se desenvolver o código de produção. O TDD foi conceitualizado por Kent Beck no livro Test Driven Development: By Example.

Tradicionalmente os desenvolvedores implementam o código primeiro verificam o código manualmente e depois escrevem os testes (se escreverem), essa forma de desenvolvimento é chamada de DLP (Debug Later Programming). O DLP contem riscos inerentes como:

  • os bugs podem se esconder no software por muito tempo, no DPL o desenvolvedor verifica o software manualmente logo ele pode errar pois é um processo entediante e repetitivo ou ele pode esquecer de verificar alguma funcionalidade. O software defeituoso pode ser descoberto diretamente no cliente onde é mais caro corrigir o erro. Podem se decorrer semanas ou meses até o  relatório de bug chegar aos programadores.
  • desenvolver os testes depois do código implementado é muito monótono, a tarefa de implementar testes sobre um código que você mesmo escreveu e verificou é muito monótona, pois você já sabe (ou pelo menos acredita) que o código está funcionando 100%.
  • corrigir um bug pode fazer diversos aparecerem, conforme explicado no primeiro ponto os bugs demoram a retornar para os programadores, logo eles continuaram desenvolvendo código sob um software defeituoso. Quando o relatório de bug chega aos programadores a correção do bug pode revelar diversos bugs que utilizavam o comportamento defeituoso como correto, isso vai aumentar exponencialmente o tempo de debug necessário para corrigir todos bugs.

Por um exemplo o Therac-25 era uma máquina de Raio-X que devido a um bug calculava algumas vezes um valor errado de emissão de radiação e como consequência matou algumas pessoas. O bug não foi descoberto e houveram graves consequências.

Qualidade de código sem TDD

O TDD resolveu os problemas introduzindo uma disciplina que força os desenvolvedores a sistematicamente implementarem o software junto com o testware (1). O desenvolvedor inicia implementando um teste que descreve o comportamento esperado para uma funcionalidade, o teste vai falhar neste momento pois a funcionalidade ainda não foi implementada. Depois do teste o desenvolvedor implementa o código para funcionalidade então o teste vai passar. Ao final o desenvolvedor melhora a redabilidade do código e re-executa os testes.

Os testes implementados pelo TDD sao automatizados e rápidos, desta forma o desenvolvedor pode verificar novas e antigas funcionalidades do software várias vezes por minuto reduzindo drasticamente o tempo entre a inserção de um bug e a sua correção. Um ciclo completo de TDD dura menos que 5 minutos, ou seja, se o desenvolvedor inseriu um bug em uma funcionalidade o bug foi inserido no máximo 5 minutos atrás.

Para aplicar o TDD o desenvolvedor deve seguir o micro-ciclo do TDD conforme os passos:

  1. Escreva um pequeno teste para uma funcionalidade
  2. Execute todos os testes e observe o novo teste falhar (não compilar é falhar)
  3. Escreva o código para a funcionalidade desejada que faça o teste passar
  4. Execute todos os testes e observe todos os testes passarem
  5. Refatore o código para melhorar a redabilidade

O micro-ciclo do TDD dura poucos minutos e por isso é muito fácil localizar e corrigir os bugs. Se no passo 4 o desenvolvedor inseriu algum bug em alguma funcionalidade antiga durante a execução dos testes o bug será revelado e será localizado facilmente pois existe um teste falhando indicando onde está o problema.

O TDD funciona como uma rede de segurança para o desenvolvedor que diminui drasticamente a possibilidade de um bug passar despercebido pelos testes, utilizando TDD o desenvolvedor garante que o seu código esta funcionando e que nao quebrou nenhuma outra funcionalidade.

O micro-ciclo do TDD também é conhecido como Red-Green-Refactor (Vermelho-Verde-Refatoração). Os frameworks de teste em geral mostram em vermelho testes que falham e em verde testes que passam e assim se originou o nome Red-Green-Refactor.

No passo 3 o desenvolvedor tem um objetivo claro, fazer o teste passar, neste ponto ele não vai se concentrar em outros aspectos como a qualidade do código. No passo 5 a funcionalidade já está implementada e testada, neste momento o desenvolvedor se concentra única e exclusivamente em melhorar a qualidade do código. Desenvolvedores experientes sabem que manter a base de código limpa é extremamente importante pois o maior custo do software não é a implementação mas sim a manutenção.

TDD apresenta os seguintes benefícios para os seus adeptos:

·         Menos bugs, pois existe uma rede de testes que protege o software contra bugs

·         Menos tempo utilizando o debugger, pois sabemos exatamente onde esta o bug devido ao teste falhando

·         Documentação atual, os testes descrevem em poucas linhas exatamente como uma funcionalidade deve se comportar portanto o testes são uma especie de documentação

·         Segurança para alterar o software, a rede de testes faz o desenvolvedor se sentir protegido para inserir mais funcionalidades sem quebrar nenhuma funcionalidade antiga

·         Design para testabilidade e modularidade, o código desenvolvido torna-se por natureza modular e testável

Software embarcado (embedded software ou firmware) possui todos os problemas de outros tipos de software e mais alguns próprios. O problema mais citado por desenvolvedores de software embarcado para não utilizarem TDD é a dependência ao hardware, eles acreditam que não é possível testar o firmware separado do hardware. Software não embarcado também possui problemas com dependências, por exemplo uma database é uma dependência de um software. O TDD possui técnicas que resolvem os problemas com dependências, sejam elas de hardware ou databases.

Os seguintes benefícios podem ser esperados quando se utiliza TDD em software embarcado:

·         Verificação do software separada do hardware, isso é muito útil pois as vezes o hardware não pode ser instrumentado para testes e em geral hardware é bem escasso e caro

·         Número reduzido de compilações e uploads longos, o desenvolvimento é feito majoritariamente no computador do desenvolvedor (host)

·         Isolamento entre hardware e software, mudar o microcontrolador do projeto é facil só é necessário adaptar os testes que acessam ao hardware

Este é o primeiro texto de uma série de textos e vídeos sobre TDD em sistemas embarcados, a série é prática e teórica portanto quem ler até o final será capaz de implementar na prática TDD para sistemas embarcados.

Se voce seguir a serie toda

Publicado

em

por

Tags: