Menos bugs, maior qualidade: TDD - Test-Driven Development

tdd

A busca pela causa de bugs é a etapa mais frustrante do processo de desenvolvimento de firmware, essa busca representa despesas imprevisíveis à gestão e esforços intensos sem retornos em proporção para os desenvolvedores, ou seja, todo mundo perde. Apontar a incidência de bugs como um dos principais vilões do desenvolvimento de sistemas embarcados não seria um exagero. Test Driven Development (TDD) é empregado justamente para diminuir a incidência de bugs. Regulando em micro passos a construção de código de produção e testes unitários o TDD vai encurtar a vida útil de um bug de dias ou meses para minutos, contanto que o desenvolvedor siga rigorosamente os micro passos do TDD, que podem ser grosseiramente resumidos a duas etapas:

 

  1. acrescente um teste e veja-o falhar;
  2. escrava o mínimo de código para vê-lo passar.

 

Ao contrário do que se espera, o teste unitário é escrito antes do código de produção, assim é codificado apenas o suficiente para fazer o teste passar. Esses testes unitários, uma vez escritos, ficam inseridos na firmware pelo resto da sua existência, e, quando a firmware receber modificações ou incrementos, eles vão proteger o código legado de eventuais corrupções. Por fim, o TDD ajuda a prevenir e detectar bugs nos dois momentos de existência de um projeto, durante o desenvolvimento e durante a manutenção ou expansão.

 

Mas TDD não é só isso, também existem outros benefícios associados ao seu uso tão importante quanto a prevenção de bugs e a diminuição do tempo gasto em debug, tais como:

 

  1. ter documentação na forma de testes: quando o cliente de um módulo precisar entender como ele é usado, basta ler os testes;
  2. aumentar a robustez: quando algum código existente for comprometido, algum teste falhará;
  3. modularizar e diminuir o acoplamento: para um código ser testável ele precisa ser escrito em módulos e desacoplado dos demais módulos;
  4. proporcionar paz de espírito: TDD passa maior segurança e por isso desenvolvedores que usam TDD dizem dormir melhor;
  5. prover monitoramento do progresso: os testes informam o que já foi implementado e está funcionado.

 

Em TDD todos os testes devem ser automatizados e rodados centenas de vezes por dia durante o desenvolvimento, por isso quando TDD é empregado em sistemas embarcados tanto os testes quanto o código de produção é escrito independente de plataforma. Além de rodar no hardware embarcado (target), também roda na máquina de desenvolvimento (host), possibilitando que a cada linha escrita os testes sejam executados, entretanto ao se escrever código independente de plataforma em sistemas embarcados fica necessário construir mocks ou fakes para simular o comportamento do hardware, mas apenas o suficiente para que módulos dependentes sejam testados, somado a isso, essa questão de dependência com o hardware é minimizada pois TDD instrúi a construir os módulos dependentes com o mínimo de funcionalidades possíveis.

 

Além dos benefícios convencionais, quando aplicado em embarcados, o TDD também apresenta outras vantagens, como:

 

  1. reduzir o risco: todo o código de produção é verificado independentemente do hardware;
  2. remover o longo processo de debug no target;
  3. isolar o hardware e a firmware;

 

Por fim, vale mencionar a definição que Jack Ganssle dá a software de qualidade: software sem bugs entregue no prazo. É justamente isso que TDD ajuda a fazer, diminui o tempo gasto na procura de bugs assim como a incidência deles no código final de produção, eleva a manutenibilidade do código e por fim melhora o desempenho e o prazer do desenvolvedor. Só se tem a ganhar.

 

Aquele que deseja aplicar TDD na sua vida de desenvolvedor, deve, obrigatoriamente, ler o livro do James Grenning chamado Test-Driven Development for Embedded C.

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

3
Deixe um comentário

avatar
 
1 Comment threads
2 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
2 Comment authors
Felipe LavrattiRobert Perez Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Robert Perez
Visitante
Robert Perez

Hola Felipe, hace tiempo quiero profundizar en los test para software embarcado pero no consigo ver como insertar tests por ejemplo en intercambio de paquetes via sockets, o funciones que requieran de una estructura de datos ya proporcionada.

Como se hace en estos casos ?

Gracias, Robert
Uruguay

Felipe Lavratti
Visitante
Felipe Lavratti

Hola Robert Perez! Veja bem, para usar TDD em sockets, por exemplo, fica um pouquinho menos óbvio. Tomamos o exemplo de construir um sistema de mandar uma struct qualquer via sockets entre dois nodos da rede. Primeiramente rodamos o ciclo teste-código para construir as rotinas de, tomamos neste caso, recebimento. Nesta etapa um módulo de recebimento vai ser escrito e a parte de envio necessária para testá-lo vai ficar definitivamente misturada dentro dos testes. Agora passamos para o próximo passo, onde vamos rodar o ciclo teste-código para escrever as rotinas de envio, mas desas vez, nós já temos o módulo… Leia mais »

Robert Perez
Visitante
Robert Perez

Gracias Felipe, es lo que me temía 🙂

Supongo que las funciones stub o mock functions como les llaman deben setear el entorno, crear estructuras, abrir sockets, etc para poder testear las funciones realmente.
Si bien el tiempo invertido en esta etapa es mucho, entiendo que termina siendo menor al tiempo usado en la depuracion.

Voy a conseguir el libro de TDD para embedded systems que recomiendas porque me he quedado enganchado con este tema.

Gracias por la info.
Abrazo desde aquí tambien !