sexta-feira, 10 de agosto de 2012

Test-Driven Development - TDD

Test-Driven Development (TDD) ( Beck 2003 ; Astels 2003 ), é uma abordagem evolutiva para o desenvolvimento que combina teste anterior de desenvolvimento onde você escreve um teste antes de escrever código de produção apenas o suficiente para executar o teste e refatoração .    Qual é o principal objetivo do TDD?   Um ponto de vista é o objetivo do TDD é a especificação e não validação ( Martin, Newkirk, e Kess 2003 ).   Em outras palavras, é uma maneira de pensar através de suas necessidades ou de design antes de escrever seu código funcional (o que implica que TDD é tanto um importante requisitos ágeis e design ágil técnica).   Outra opinião é que TDD é uma técnica de programação.   Como Ron Jeffries gosta de dizer, o objetivo do TDD é escrever código limpo que funciona.   Eu acho que há mérito em ambos os argumentos , embora eu prefira  a visão da especificação, mas deixo para você decidir.

1. O que é TDD ?
As etapas de desenvolvimento de teste (TFD) é supervisionada no diagrama de atividade UML da Figura 1 . O primeiro passo é adicionar rapidamente um teste, o código basicamente  o suficiente para falhar. Em seguida, você executa seus testes, muitas vezes, a suíte de testes e completa embora por causa da velocidade que você pode decidir executar apenas um subconjunto, para garantir que o novo teste é de fato falhar. Você, então, atualizar seu código funcional para fazê-lo passar nos novos testes. O quarto passo é executar os testes novamente. Se eles falharem você precisa atualizar seu código funcional e teste novamente. Uma vez que os testes de passar o próximo passo é começar de novo (talvez seja necessário para refatorar qualquer duplicidade de seu projeto, conforme necessário, transformando o TFD em TDD).

Figura 1. As etapas de teste-primeiro desenvolvimento (TFD) 

 Eu gostaria de descrever o TDD com esta fórmula simples:

   TDD Refactoring = + TFD.

TDD muda completamente o desenvolvimento tradicional. Quando você vai implementar um novo recurso, a primeira questão que se pergunta é se o design existente é o melhor projeto possível que lhe permite implementar esta funcionalidade. Se assim for, proceder através de uma abordagem TFD. Se não, você refatorar localmente para mudar a parte do projeto afetada pela nova funcionalidade, permitindo-lhe adicionar esse recurso tão fácil quanto possível. Como resultado, você será sempre a melhoria da qualidade de seu projeto, tornando assim mais fácil trabalhar com, no futuro.

. Em vez de escrever código funcional primeiro e depois o código de teste como um adendo, se você escrevê-lo em tudo, você deve escrever o código de teste antes de seu código funcional   Além disso, você fazê-lo em passos muito pequenos - um teste e um pequeno pedaço de código funcional correspondente ao mesmo tempo.   Um programador de uma abordagem TDD se recusa a escrever uma nova função até que haja primeiro um teste que falhe porque esta função não está presente.   Na verdade, eles se recusam a adicionar uma única linha de código até que uma teste existe para ele.   Uma vez que o teste está no lugar que, em seguida, fazer o trabalho necessário para garantir que o conjunto de testes passa agora (o novo código pode quebrar alguns dos testes existentes, bem como a nova).   Isso parece simples, em princípio, mas quando você está aprendendo a ter uma abordagem TDD prova exige muita disciplina, porque é fácil "escorregar" e escrever o código funcional sem escrever um novo teste.   Uma das vantagens da programação em pares é que o seu par ajuda-o a permanecer na pista .

Existem dois níveis de TDD:

Aceitação TDD (ATDD) . Com ATDD você escreve um único teste de aceitação , ou especificação comportamental, dependendo da sua terminologia preferida, e, em seguida, apenas o suficiente funcionalidade de produção / código para executar o teste. O objetivo do ATDD é especificar detalhados, requisitos executáveis ​​para sua solução em uma só base no tempo (JIT). ATDD também é chamado de Behavior Driven Development (BDD).

Desenvolvedor TDD . Com desenvolvedor TDD você escreve um teste único desenvolvedor, por vezes, erroneamente referido como um teste de unidade, e então código de produção apenas o suficiente para executar o teste. O objetivo do desenvolvedor TDD é especificar um projeto detalhado e executável para sua solução em uma base JIT. Desenvolvedor TDD é muitas vezes chamado simplesmente TDD.

A Figura 2 mostra um diagrama de atividade UML mostrando como ATDD e desenvolvedor TDD se encaixam. Idealmente, você vai escrever um teste de aceitação única, em seguida, para implementar o código de produção necessário para executar o teste você vai ter um desenvolvedor abordagem TDD. Este, por sua vez exige que você iterar várias vezes ao longo do ciclo escrever um teste, escreva o código de produção, fazê-lo funcionar no nível TDD desenvolvedor.


Figura 2. Como aceitação TDD TDD e desenvolvedor trabalham juntos.

Note que a Figura 2 pressupõe que você está fazendo ambos, embora seja possível fazer qualquer um sem o outro. De fato, algumas equipes farão desenvolvedor TDD sem fazer ATDD, ver os resultados da pesquisa abaixo , mas se você está fazendo ATDD então é praticamente certo que você está fazendo também desenvolvedor TDD. O desafio é que ambas as formas de TDD requer profissionais ter habilidades de ensaios técnicos, habilidades que os profissionais de exigência muitas vezes não têm (ainda outra razão pela qual especialistas generalizantes são preferíveis para os especialistas).
Um pressuposto subjacente de TDD é que você tem uma estrutura de teste disponível para você.   Para as pessoas de aceitação TDD usará ferramentas como Fitnesse ou RSpec e para desenvolvedor TDD alguns desenvolvedores de software Gile freqüentemente usam a família xUnit de ferramentas de código aberto, tais como JUnit ou VBUnit , embora as ferramentas comerciais também são opções viáveis.   Sem tais ferramentas TDD é praticamente impossível. Figura 3 apresenta um diagrama de estados UML de como as pessoas normalmente trabalham com essas ferramentas. Este diagrama me foi sugerido por Keith Ray.



Figura 3. Testando com o Framework xUnit.
Kent Beck, que popularizou o TDD em eXtreme Programming (XP) ( Beck, 2000 ), define duas regras simples para TDD ( Beck 2003 ).   Primeiro, você deve escrever código novo negócio apenas quando um teste automatizado falhou.   Em segundo lugar, você deve eliminar qualquer . duplicação que você encontra   Beck explica como essas duas regras simples gerar indivíduo complexo e comportamento de grupo:

Você desenvolve organicamente, com o código executando fornecimento de feedback entre as decisões.

Você escreve seus próprios testes porque você não pode esperar 20 vezes por dia para alguém para escrevê-los para você.

Seu ambiente de desenvolvimento deve oferecer uma resposta rápida a pequenas alterações (por exemplo, você precisa de um compilador rápido e um conjunto de testes de regressão).

Seus desenhos devem ser constituídos de componentes altamente coesivos, fracamente acoplados (por exemplo, seu design é altamente normalizado) para fazer o teste mais fácil (o que também torna a evolução e manutenção do seu sistema mais fácil também).


Para os desenvolvedores, a implicação é que eles precisam aprender a escrever testes de unidade eficazes.   experiência de Beck é que bons testes:

Corra rápido (eles têm configurações curtas, execução e finalização).

Executar de forma isolada (você deve ser capaz de reordená-las).

Use os dados que torna fácil de ler e de entender.

Use os dados reais (por exemplo, cópia de dados de produção) quando eles precisam.

Representam um passo em direção ao seu objetivo global.
2. teste TDD e Tradicional

TDD é basicamente uma técnica de especificação com um efeito colateral de garantir que seu código-fonte é testado em um nível de confirmação.   No entanto, há mais testes do que isso.   Particularmente em escala y ou'll ainda precisa considerar outros testes ágeis tais técnicas como pré-produção de testes de integração e testes de investigação .   Muito deste teste também pode ser feito no início de seu projeto se você optar por fazê-lo (e deverá).

Com os testes tradicionais um teste bem sucedido encontra um ou mais defeitos.   É o mesmo com TDD, quando um teste falhar, você têm feito progressos, porque agora sabe que você precisa para resolver o problema.   Mais importante, você tem uma medida clara de sucesso quando o teste não falha mais. TDD aumenta a sua confiança de que seu sistema realmente atende aos requisitos definidos para ele, que o sistema realmente funciona e, portanto, você pode prosseguir com confiança.


Tal como acontece com os testes tradicionais, o maior perfil de risco do sistema dos mais completos os testes precisam ser. Com ambos os testes tradicionais e TDD você não está buscando a perfeição, em vez você está testando a importância do sistema. Parafraseando Agile Modeling (AM) , você deve "testar com um propósito" e saber por que você está testando algo e em que nível ele precisa ser testado. Um efeito colateral interessante de TDD é que você consegue teste 100% de cobertura - cada linha de código é testado - algo que os testes tradicionais não garante (embora não recomendo). Em geral, eu acho que é bastante seguro dizer que, embora TDD é uma técnica de especificação, um efeito colateral importante é que ela resulta em um código significativamente melhor do que as técnicas tradicionais.  
Se vale a pena construir, vale a pena testar.

Se não a pena testar, por que você está desperdiçando seu tempo a trabalhar nele?
3. TDD e Documentação
Goste ou não a maioria dos programadores não ler a documentação escrita para um sistema, em vez disso, preferem trabalhar com o código. E não há nada de errado com isso. Ao tentar compreender a maioria dos programadores de classe ou operação vai procurar primeiro pelo código de exemplo que já chama-lo. Testes de unidade bem escritos fazem exatamente isso - a fornecer uma especificação de trabalho de seu código funcional - e como uma unidade resultado testa se tornar efetivamente uma parcela significativa de sua documentação técnica. A implicação é que as expectativas da multidão pró-documentação precisa refletir essa realidade. Da mesma forma, os testes de aceitação pode formar uma parte importante da documentação de requisitos. Isso faz muito sentido quando você parar e pensar sobre isso. Seus testes de aceitação definir exatamente o que seus stakeholders esperam do sistema, portanto, especificar os requisitos críticos. Seu conjunto de testes de regressão, particularmente com uma abordagem de teste de primeira, torna-se efetivamente detalhadas especificações executáveis ​​.

Os testes de documentação suficiente? Muito provavelmente não, mas eles formam uma parte importante dela. Por exemplo, é provável que você achar que você ainda precisa do usuário do sistema, visão geral, operações e documentação de suporte. Você pode até achar que você precisar de documentação resumida do processo de negócio que o sistema suporta. Quando você se aproxima de documentação com uma mente aberta, eu suspeito que você vai achar que estes dois tipos de testes de cobrir a maioria de sua documentação precisa para desenvolvedores e stakeholders. Além disso, são um exemplo maravilhoso de AM da prática de fonte única de informação e uma parte importante de seus esforços globais para ficar tão ágil como a documentação relativa possível .
4. Test-Driven Development banco de dados

No momento da redação deste texto uma questão importante a ser feita na comunidade ágil "pode ​​TDD trabalhar para o desenvolvimento orientado a dados?" Quando você olha para o processo representado na Figura 1 , é importante notar que nenhuma das etapas especificar programação objeto linguagens, como Java ou C #, mesmo que esses são os ambientes de TDD é tipicamente usados ​​dentro Por que você não poderia escrever um teste antes de fazer uma mudança de esquema do banco de dados? Por que você não poderia fazer a mudança, executar os testes e refatorar seu esquema como necessária? Parece-me que você só precisa escolher a trabalhar desta forma.

Meu palpite é que no curto prazo do banco de dados TDD, ou talvez Teste Database Design Driven (TDDD), não vai funcionar tão bem como aplicação TDD. O primeiro desafio é o suporte da ferramenta. Embora unidade de teste de ferramentas, tais como DBUnit , estão agora disponíveis ainda são uma tecnologia emergente no momento da redação deste texto. Alguns DBAs estão melhorando a qualidade dos testes que estão fazendo, mas eu ainda não vi ninguém fazer uma abordagem TDD para o desenvolvimento de banco de dados. Um desafio é que as ferramentas de testes de unidade ainda não são bem aceitos na comunidade de dados, embora isso esteja mudando, por isso a minha expectativa é que ao longo dos próximos anos, banco de dados TDD vai crescer. Em segundo lugar, o conceito de desenvolvimento evolutivo é novo para muitos profissionais de dados e como resultado a motivação para tomar uma abordagem TDD ainda tem que se firmar. Esse problema afeta a natureza das ferramentas disponíveis para profissionais de dados - porque uma mentalidade de série ainda domina dentro da comunidade tradicional a maioria das ferramentas não suportam desenvolvimento evolutivo. Minha esperança é que os fornecedores de ferramentas vai pegar para essa mudança de paradigma, mas a minha expectativa é de que vamos precisar para desenvolver ferramentas de código aberto. Em terceiro lugar, a minha experiência é que a maioria das pessoas que fazem trabalho orientado dados parecem preferir um modelo orientado, e não uma abordagem test-driven. Uma das causas disso é provável, porque uma abordagem test-driven não tem sido amplamente considerada até agora, outra razão pode ser que muitos profissionais são susceptíveis de dados visuais e por isso preferem uma abordagem orientada a modelos.

5. Escala TDD via Agile Model-Driven Development (AMDD )

TDD é muito bom em especificação detalhada e validação, mas não tão boa para pensar em questões maiores, tais como a concepção global, como as pessoas irão usar o sistema, ou o design da interface (por exemplo). Modelagem, ou mais até o ponto de desenvolvimento orientado por modelo ágil (AMDD) (o ciclo de vida para a qual é capturada em Figura 4 ) é mais adequado para isso. AMDD aborda as dimensionamento ágeis questões que TDD não faz.

Figura 4 . O Modelo de Desenvolvimento Ágil Dirigido ciclo de vida (AMDD).


6. Por TDD?
Uma vantagem significativa do TDD é que ele permite que você tomar pequenos passos ao escrever software.   Esta é uma prática que eu tenho promovido por anos porque é muito mais produtivo do que tentar codificar em passos largos.   Por exemplo, suponha que você adicionar alguma nova código funcional, compilar e testar.   chances são muito boas que os testes serão quebrados por defeitos que existem no novo código.   É muito mais fácil de encontrar, e então reparar, estes defeitos se você escreveu duas novas linhas de código de dois mil. A implicação é que quanto mais rápido o seu compilador e conjunto de teste, o mais atraente é continuar com passos cada vez menores.   Eu geralmente preferem adicionar algumas linhas novas de código funcional, tipicamente menos de 10, antes de recompilar e executar novamente o meu testes.

Eu acho que Bob Martin diz que "o ato de escrever um teste de unidade é mais um ato de desígnio e não de verificação.   É também mais um ato de documentação do que de verificação.   O ato de escrever um teste de unidade fecha um grande número de comentários loops, menos do que é o único pertencente a verificação da função ".

A primeira reação que muitas pessoas têm de técnicas ágeis é que elas funcionam bem para projetos pequenos, talvez envolvendo um punhado de pessoas durante vários meses, mas que não iria trabalhar para "reais" projetos que são muito maiores.    Isso simplesmente não é verdade. Beck (2003) relatórios de trabalho em um sistema de Smalltalk uma abordagem totalmente orientado a testes, que teve 4 anos e 40 anos pessoa de esforço, resultando em 250.000 linhas de código funcional e 250.000 linhas de código de teste. Existem testes de corrida em 4000 menos de 20 minutos, com o conjunto completo que está sendo executado várias vezes ao dia. Embora existam sistemas de grande porte lá fora, eu pessoalmente trabalhei em sistemas onde várias centenas de pessoas-ano de esforço foram envolvidos, é claro que TDD trabalha para bom tamanho sistemas.      

7. Mitos e Equívocos
Existem vários mitos e concepções erradas comuns que as pessoas têm sobre TDD que eu gostaria de esclarecer se possível.

Nenhum comentário:

Postar um comentário