Tenho apenas mais de 2 anos de experiência em desenvolvimento de aplicativos. Naqueles dois anos, minha abordagem para o desenvolvimento foi a seguinte
- Analisar requisitos
- Objeto / objetos principais de identidade, funções necessárias, comportamento, processo e suas restrições
- Criar classes, relação entre elas, restrições no comportamento e estados dos objetos
- Criar funções, processar com restrições comportamentais conforme os requisitos
- Teste manualmente o aplicativo
- Se as alterações dos requisitos modificarem componentes / funções, teste manualmente o aplicativo
Recentemente, fui apresentado ao TDD e sinto que essa é uma maneira muito boa de desenvolver o desenvolvimento, pois o código desenvolvido tem fortes motivos para existir e muitos problemas pós-implantação são atenuados.
Mas meu problema é que não sou capaz de criar testes primeiro. Em vez disso, estou identificando componentes e apenas escrevendo testes para eles antes de realmente escrever componentes. minha pergunta é
- Estou fazendo certo? Se não, o que exatamente eu tenho que mudar
- Existe alguma maneira de identificar se o teste que você escreveu é suficiente?
- É uma boa prática escrever teste para uma funcionalidade muito simples, que pode ser equivalente a 1 + 1 = 2 ou é apenas um exagero?
- É bom alterar a funcionalidade e testar adequadamente se o requisito muda?
Respostas:
É difícil dizer apenas a partir dessa breve descrição, mas suspeito que não, você não está fazendo certo. Nota: Não estou dizendo que o que você está fazendo não funciona ou é de alguma forma ruim, mas você não está fazendo TDD. O meio "D" significa "Dirigido", os testes conduzem tudo, o processo de desenvolvimento, o código, o design, a arquitetura, tudo .
Os testes informam o que escrever, quando escrever, o que escrever a seguir, quando parar de escrever. Eles dizem o design e a arquitetura. (O design e a arquitetura emergem do código por meio da refatoração.) O TDD não se refere a testes. Nem se trata de escrever testes primeiro: o TDD é permitir que os testes o conduzam, escrevê-los primeiro é apenas um pré-requisito necessário para isso.
Não importa se você realmente escreve o código ou o detalha completamente: você está escrevendo (esqueletos de) código em sua cabeça e depois escrevendo testes para esse código. Isso não é TDD.
Abandonar esse hábito é difícil . Muito, muito difícil. Parece ser especialmente difícil para programadores experientes.
Keith Braithwaite criou um exercício que ele chama de TDD como se você quisesse . Ele consiste em um conjunto de regras (baseadas nas Três Regras do TDD do tio Bob Martin , mas muito mais rigorosas) que você deve seguir rigorosamente e que foram projetadas para orientá-lo a aplicar o TDD com mais rigor. Funciona melhor com a programação de pares (para que seu par possa garantir que você não está infringindo as regras) e com um instrutor.
As regras são:
Normalmente, isso levará a designs muito diferentes do que o "método pseudo-TDD" comumente praticado de "imaginar em sua cabeça qual deveria ser o design e, em seguida, escrever testes para forçar esse design, implementar o design que você já havia previsto antes de escrever seu testes ".
Quando um grupo de pessoas implementa algo como um jogo do tic tac toe usando pseudo-TDD, eles geralmente terminam com projetos muito semelhantes, envolvendo algum tipo de
Board
classe com uma matriz 3 x 3 deInteger
s. E pelo menos uma parte dos programadores realmente escreveu essa classe sem testes, porque "sabem que vão precisar" ou "precisam de algo para escrever seus testes". No entanto, quando você força esse mesmo grupo a aplicar o TDD como se você quisesse, eles geralmente acabam com uma grande diversidade de designs muito diferentes, geralmente sem empregar nada remotamente semelhante a umBoard
.Quando eles cobrem todos os requisitos de negócios. Os testes são uma codificação dos requisitos do sistema.
Novamente, você tem o inverso: você não escreve testes de funcionalidade. Você escreve funcionalidade para testes. Se a funcionalidade para passar no teste for trivial, isso é ótimo! Você acabou de cumprir um requisito de sistema e nem sequer trabalhou duro para isso!
Não. O contrário. Se um requisito for alterado, você modifica o teste que corresponde a esse requisito, observa-o falhar e altera o código para fazê-lo passar. Os testes sempre vêm em primeiro lugar.
É difícil fazer isso. Você precisa de dezenas, talvez centenas de horas de prática deliberada , a fim de criar algum tipo de "memória muscular" para chegar a um ponto em que, quando o prazo se aproxima e você está sob pressão, nem precisa pensar nisso. , e fazer isso se torna a maneira mais rápida e natural de trabalhar.
fonte
Board
classe com um Matriz 3x3 deint
s (ou algo parecido). Considerando que, se você forçá-los a fazer TDDAIYMI, eles geralmente acabam criando um mini-DSL para capturar o conhecimento do domínio. Isso é apenas anedótico, é claro. Um estudo estatisticamente e cientificamente correto seria bom, mas, como é comum em estudos como esse, eles são muito pequenos ou muito caros.Você descreve sua abordagem de desenvolvimento como um processo "de cima para baixo" - você começa a partir de um nível de abstração mais alto e entra cada vez mais nos detalhes. TDD, pelo menos na forma como é popular, é uma técnica "de baixo para cima". E para alguém que trabalha principalmente de cima para baixo, pode ser realmente muito incomum trabalhar de baixo para cima.
Então, como você pode trazer mais "TDD" ao seu processo de desenvolvimento? Primeiro, suponho que seu processo de desenvolvimento real nem sempre seja "de cima para baixo", como você descreveu acima. Após a etapa 2, você provavelmente terá identificado alguns componentes que são independentes de outros componentes. Às vezes, você decide implementar esses componentes primeiro. Os detalhes da API pública desses componentes provavelmente não seguem apenas seus requisitos, os detalhes também seguem suas decisões de design. Este é o ponto em que você pode começar com o TDD: imagine como você usará o componente e como você realmente usará a API. E quando você começa a codificar esse uso da API na forma de teste, você começou com o TDD.
Segundo, você pode executar o TDD mesmo quando codificar mais de cima para baixo, começando com componentes que dependem primeiro de outros componentes não existentes. O que você precisa aprender é como "zombar" dessas outras dependências primeiro. Isso permitirá que você crie e teste componentes de alto nível antes de ir para os componentes de nível inferior. Um exemplo muito detalhado de como fazer TDD de maneira descendente pode ser encontrado neste post de Ralf Westphal .
fonte
Você está indo muito bem.
Sim, use uma ferramenta de cobertura de teste / código . Martin Fowler oferece alguns bons conselhos sobre a cobertura dos testes.
Em geral, qualquer função, método, componente etc. que você espere obter algum resultado, dadas algumas entradas, é um bom candidato para um teste de unidade. No entanto, como na maioria das coisas na vida (engenharia), você precisa considerar suas vantagens e desvantagens: O esforço é compensado ao escrever o teste de unidade, resultando em uma base de código mais estável a longo prazo? Em geral, opte por escrever o código de teste para a funcionalidade crucial / crítica primeiro. Posteriormente, se você encontrar erros associados a alguma parte não testada do código, adicione mais testes.
O bom de ter testes automatizados é que você verá imediatamente se uma alteração quebra as afirmações anteriores. Se você espera isso por causa de requisitos alterados, sim, não há problema em alterar o código de teste (na verdade, no TDD puro, você alteraria os testes primeiro de acordo com os requisitos e depois adotaria o código até que atendesse aos novos requisitos).
fonte
Escrever testes primeiro é uma abordagem completamente diferente para escrever software. Os testes não são apenas uma ferramenta de verificação adequada da funcionalidade do código (todos passam), mas a força que define o design. Embora a cobertura do teste possa ser uma métrica útil, ela não deve ser o objetivo em si - o objetivo do TDD não é obter uma boa% da cobertura do código, mas pensar na testabilidade do seu código antes de escrevê-lo.
Se você tiver problemas com a escrita de testes primeiro, eu recomendo fazer uma sessão de programação em pares com alguém com experiência em TDD, para que você tenha uma experiência prática sobre "a maneira de pensar" sobre toda a abordagem.
Outra coisa boa a se fazer é assistir a vídeos on-line nos quais o software está sendo desenvolvido usando TDD desde a primeira linha. Uma boa que eu costumava me apresentar ao TDD foi o Let's Play TDD de James Shore. Dê uma olhada, ele ilustrará como o design emergente funciona, que perguntas você deve se perguntar ao escrever testes e como novas classes e métodos são criados, refatorados e iterados.
Eu acredito que esta é a pergunta errada a ser feita. Quando você faz TDD, você escolhe o TDD e o design emergente como a maneira de escrever software. Se qualquer nova funcionalidade que você precisar adicionar sempre começar com um teste, ela sempre estará lá.
Obviamente, depende, use seu julgamento. Prefiro não escrever testes nas verificações nulas dos parâmetros, se o método não fizer parte da API pública, mas, caso contrário, por que você não confirmaria que o método Add (a, b) retorna a + b, de fato?
Novamente, quando você altera ou adiciona nova funcionalidade ao seu código, você começa com um teste, seja adicionando novo teste ou alterando um existente quando os requisitos mudam.
fonte