Há pouco mais de um ano, tive a sorte de poder tirar uma folga de 9 meses do trabalho. Decidi que, naquele tempo, aperfeiçoaria minhas habilidades em C #. Comecei a trabalhar em vários projetos e me forcei a seguir o TDD.
Foi um processo bastante esclarecedor.
Foi difícil no começo, mas com o tempo aprendi a escrever código mais testável (que, como se vê, tende a ser mais código SOLID) e, no processo, também aprimorei minha habilidade em design de OO.
Agora estou de volta à força de trabalho e estou percebendo algo estranho.
Eu prefiro não seguir TDD.
Acho que o TDD me deixa mais lento e torna mais difícil projetar um aplicativo limpo.
Em vez disso, adotei uma abordagem ligeiramente (massivamente) diferente:
- Escolha uma fatia vertical do trabalho
- Desenvolver um protótipo funcional
- Refatorar até que tudo esteja agradável e arrumado
- Relaxe e aprecie o código lindamente sólido e testável que escrevi.
Você deve ter notado que a etapa 1 não foi "definir a superfície pública do meu alvo de teste" e a etapa 2 não foi "testar o bejesus a partir dessa superfície pública". Você também deve ter notado que nenhuma das etapas envolve testes. Estou escrevendo código testável, mas não estou testando ... ainda.
Agora, gostaria de deixar claro que na verdade não estou renunciando a nenhum tipo de teste. O código que estou escrevendo funciona . Funciona porque estou testando manualmente.
Também gostaria de deixar claro que também não estou renunciando a todos os testes automatizados. É aqui que meu processo é diferente. E é por isso que estou fazendo essa pergunta.
TDD em teoria. Não na prática.
Meu processo evoluiu um pouco e encontrei um equilíbrio entre TDD e nenhum teste que considero muito produtivo e também razoavelmente seguro. É o seguinte:
- Implemente uma fatia de trabalho vertical de trabalho tendo em mente os testes, mas não escreva nenhum teste.
- Se no caminho (por exemplo, um mês depois), essa fatia precisa ser modificada
- Escreva Testes de Unidade, Testes de Integração, Testes de Comportamento, etc., que garantam que a fatia do trabalho esteja correta
- Modifique o código
- Se essa fatia não precisar de modificação,
- Fazer nada
Simplesmente mudando o fardo de escrever testes de antes de escrever o código para antes de modificar o código, eu pude produzir muito mais código funcional. E, quando passo a escrever testes, escrevo muito menos deles, mas abro quase o mesmo terreno (maior ROI).
Gosto desse processo, mas estou preocupado que ele possa não ser bem dimensionado. Seu sucesso depende de desenvolvedores serem diligentes em escrever testes antes de mudarem as coisas. E isso parece ser um risco muito grande. Mas, o TDD tem o mesmo risco.
Então, eu estou indo para o inferno, ou isso é uma forma comum de codificação e testes pragmáticos?
Eu gostaria de continuar trabalhando dessa maneira. O que posso fazer para que esse processo funcione a longo prazo?
Nota:Sou o único desenvolvedor dos meus projetos e sou responsável por tudo: coleta de requisitos, design, arquitetura, teste, implantação etc. Suspeito que é por isso que meu processo está funcionando.
fonte
If that slice doesn't need modification
. lizkeogh.com/2012/06/24/beyond-test-driven-developmentRespostas:
Para que o processo funcione a longo prazo, eu escreveria os testes quando o código estiver sendo escrito.
O que pode parecer contradizer sua abordagem. No entanto, você fez a pergunta, então eu darei a você a minha opinião:
Você não precisa escrever os testes antes do código. esqueça essa pureza. No entanto, você quer escrever os testes em todo esse tempo.
Depois que o código está funcionando, você o aprimorou um pouco, eliminou alguns bugs (estamos falando de uma escala de horas aqui), então você está em um ponto de conhecimento máximo sobre o que o código está fazendo. Este é um ótimo momento para escrever testes que capturam seu conhecimento.
Deixar isso para depois significa que o conhecimento (naturalmente) diminuirá com o tempo.
Isso também significa que, se você sair e mais alguém assumir o controle, não terá a dívida técnica imediata de não ter documentado (por meio de testes) o que faz o quê.
Acima de tudo, "algum dia" pode não chegar. Você pode ser atropelado por um ônibus ou pode embarcar no ônibus para novas aventuras.
Por fim, o teste manual não é escalável e frequentemente não abrange todos os dispositivos usados pelo usuário final.
fonte
Embora o TDD seja difícil de implementar 100%, há uma falha na sua abordagem
Implementar uma fatia vertical de trabalho
1,1 1 ano passa ....
1.2 Um novo desenvolvedor começa a trabalhar no projeto
Se essa fatia precisar de modificação
2.3 Analisar os nomes e parâmetros do método de estilo 'Clean Coding' 'GetUnicorn (colourOfUnicorn)'
2.4 Leia os comentários xml 'Obtém um unicórnio de ouro (para cavalgar) (obvs)'
2.5 Caçar o desenvolvedor original
2.6 Espero que eles se lembrem do que o código deve fazer
2.7 Faça com que expliquem tudo
Escreva Testes de Unidade, Testes de Integração, Testes de Comportamento, etc. que esperam garantir que a fatia de trabalho esteja correta
Acho que você está certo ao identificar que os testes de unidade realmente mostram seu valor quando são necessárias modificações.
fonte
Concordo com Daniel Hollinrake e Ewan, que o primeiro ponto-chave do motivo pelo qual o seu teste apenas se modificar funciona até agora é:
e que um provável segundo ponto-chave é:
Eu não acho que o TDD traga um enorme aumento de produtividade para programadores únicos e talvez não melhore enormemente a qualidade do seu código se você já estiver escrevendo um bom código limpo.
No entanto, o TDD certamente melhorará a qualidade do código de programadores ruins / inexperientes / obsoletos, especialmente quando chegar a hora de modificar o código sem interromper nada mais. E ainda mais se a pessoa que modificou o código não for a mesma pessoa que escreveu o código originalmente ou vários meses se passaram.
Em outras palavras, acho que o TDD é uma boa prática para melhorar a qualidade do seu código (como você se reconhece), mas também (e mais importante) um tipo de proteção quando você está trabalhando com programadores médios ou medíocres (por exemplo, de um departamento ou empresa diferente), que é uma situação muito mais comum do que trabalhar sozinho.
fonte
Para mim, a principal coisa parece ser esta:
Isso funciona para você e você está produzindo um bom código limpo (presumo!). A única coisa que eu diria que você precisa fazer é criar um equipamento de teste para que outros desenvolvedores possam entrar e ter confiança em fazer alterações. Além disso, o equipamento de teste garante consistência no comportamento do código.
Eu acho que sua abordagem é semelhante à minha. Normalmente sou o único desenvolvedor em meus projetos. Descobri que uma apreciação do TDD me permitiu escrever funções menores e código mais limpo, mas adiciono testes enquanto escrevia o código como um equipamento de teste. Dessa forma, à medida que o código evolui e a funcionalidade muda, posso estar razoavelmente confiante ao fazer alterações.
Uma razão secundária para escrever testes é que eu sinto que eles são uma forma de documentação. Eles podem explicar meus raciocínios por trás de por que uma função foi criada. Mas aqui, estou pensando mais sobre o desenvolvimento orientado a comportamentos.
fonte
O Teste de Unidade trata do problema de manter o código. Embora existam pessoas que dizem que escrevem mais rapidamente código com TDD do que sem, não estou surpreso que você consiga escrever mais código novo sem escrever testes.
Os problemas que eu posso ver com a prática de escrever testes antes de você alterá-lo:
Muitas vezes preciso fazer alterações com pressa
Embora você possa economizar tempo no geral, apenas escrevendo testes quando precisar deles, nem todo o tempo é igual. Gastar 2 horas escrevendo testes para economizar 1 hora quando estou no modo de crise - vale totalmente a pena.
É mais fácil escrever testes ao mesmo tempo em que escrevo o código
Para escrever corretamente os testes de unidade, você precisa entender o código que estou testando. Costumo usar o teste de unidade como um exercício de entendimento, mas o teste de unidade do código existente pode ser demorado, porque a compreensão do código existente é demorada. Compare isso ao escrever testes enquanto você escreve o código e você o encontrará muito mais rápido porque você já entende o código - você acabou de escrever!
A definição de Michael Feathers do código legado é código sem testes. Independentemente de você concordar com a definição dele, fica claro que uma parte substancial do custo da modificação do código existente está garantindo que ele ainda funcione conforme o esperado, geralmente nem é claro qual é o comportamento esperado.
Escrever testes de unidade compensa as compensações que custam, codificando uma compreensão do que é o comportamento correto, além de fornecer uma maneira fácil para o "futuro nós" verificar se o comportamento ainda está correto.
fonte
Esta é uma boa pergunta, e FWIW eu jogarei meus dois centavos.
Há cerca de um ano, eu estava codificando no Salesforce, uma plataforma que tinha um mecanismo entranhado que o obrigava a não necessariamente escrever testes antes de codificá- lo , mas o obrigava a escrever testes em geral.
A maneira como funcionou foi que o sistema o forçaria a escrever testes e faria um cálculo do número de linhas do seu código que foram testadas em uma porcentagem. Se todo o código em toda a sua instância de produção cair abaixo de 75% testado. O Salesforce não funcionará mais.
O resultado final disso foi que toda vez que você fazia algo no Salesforce, precisava escrever ou atualizar testes. Embora eu tenha certeza de que isso tem um enorme impacto na participação de mercado do Salesforce, em termos da vida de um desenvolvedor , foi uma enorme dor de cabeça .
Na maioria das vezes, você estava apenas tentando obter um ticket pequeno e, em seguida, o teste entra e dobra seu tempo de desenvolvimento, para um recurso que você sabe que funciona.
Então, o estranho conceito de TDD varreu nosso departamento, até nossos bancos de dados. Nossos arquitetos queriam realizar testes completos em todos os aspectos do nosso departamento de TI. Ligeira dor na bunda, encontre uma dor ainda maior na bunda.
Naquela época, o TDD realmente não fazia sentido para mim, e mesmo agora ainda não faz. Muitas das funcionalidades que escrevi na minha função atual ocorrem em um mecanismo semelhante ao que você mencionou: em fatias verticais que refino até que funcionem. Quando eu estava no antigo cargo, e agora ainda não sei o que meu código vai fazer até que eu o escreva , então a ideia de que eu possa escrever testes para conduzir o código é que vou escrever apenas. não faz sentido para mim, é complicado, e principalmente uma perda de tempo.
Tudo isso dito, testes são coisas maravilhosas e mágicas que fazem tudo certo no mundo . Eles corrigem seu código, garantem que seu aplicativo faça o que você pensa e geralmente tudo mais suave. A questão então não é se você escreve seus testes antes de codificar ou depois de codificar, a questão é quanto tempo você vai se comprometer com o teste. Esse é o verdadeiro problema, pelo menos na minha experiência em desenvolvimento de software. Testar exige tempo e dinheiro e você deve fazê-lo dentro da estrutura de interesses concorrentes.
E assim, em geral, eu concordo com você: o TDD na prática é um pouco estranho e complicado. Nesse ponto, você precisa ter em mente o que funciona melhor na sua situação atual . Se você estiver escrevendo um código crítico, verifique se ele foi testado em geral. Se você tiver tempo, experimente o TDD e veja se isso acrescenta algo ao processo.
fonte
Eu não poderia recomendar sua abordagem.
Se eu usar sua abordagem, seria, por exemplo, o seguinte (a casa é a aplicação):
Portanto, sua abordagem custa muito tempo e muito conhecimento antes que eu construa a casa com sua abordagem. Ou leva muito tempo! Também não é muito gentil deixar outros testes de gravação para o seu código quando os requisitos forem alterados.
Portanto, existe uma abordagem melhor sem programar um "protótipo" e depois iniciar a refatoração. Em vez de programar um protótipo "faça um Design com UML do seu aplicativo da seguinte maneira.
Certamente, essa abordagem também precisa de algum conhecimento em UML, mas é rápida de aprender. E é sempre mais rápido renomear uma classe ou mover setas em um digram do que em seu IDE. Mas aprender o uso de estruturas de teste será mais exaustivo no começo. Best está aqui para testar os projetos de código aberto e verificar como eles funcionam. Mas quando você possui um aplicativo orientado a teste, o próximo aplicativo será muito mais rápido. E acho que é bom saber que tudo funciona bem.
Então, acabei de votar nas abordagens, porque elas consomem muito tempo para iniciantes e não são boas, afinal. Para ter uma borda limpa entre sua estrutura e o comportamento, você pode usar o Design orientado a domínio e em Organizar muito domínio com dois pacotes (um pacote denominado estrutura e o outro chamado comportamento). Também para seus testes. exemplo simples, confira este exemplo escrito em java.
fonte
Você testou manualmente todas as ramificações possíveis de suas condições após poucas alterações? Quanto tempo leva no ciclo de feedback do seu teste manual. Quão perto você fica do ciclo de feedback dos testes automatizados.
Testes automatizados (não importa primeiro ou não) fazem com que você vá rápido - fornecendo um loop de feedback mais rápido no seu código.
Tem certeza de que se lembrará de testar alguma condição manualmente após seis meses - não diga que documentará todas as condições importantes a serem testadas - porque escrever tipo de documentação / comentário é igual a escrever teste (documentação executável)
E novamente: durante a refatoração, você testou manualmente toda a lógica afetada pela refatoração? Quanto tempo leva para testar a refatoração de alterações? Se a refatoração quebrar algum código, quanto tempo leva para você encontrar um motivo para a quebra?
O código bonito e limpo de que você gostou é muito subjetivo. Seu código pode ser limpo e razoável para você. O melhor método para verificar se seu código é realmente legível, compreensível e testável são testes e análises de código feitas por outros desenvolvedores.
Você encontrou o seu caminho muito produtivo apenas porque você é apenas desenvolvedor trabalhando com o código e, eu acho, porque você está começando a trabalhar neste projeto (quantos anos você trabalha nesse projeto? 6 a 8 meses?).
Você ainda se lembra de tudo que escreveu e pode reconhecer uma razão para possíveis problemas. Tenho certeza de que você começará a escrever testes do início após 2 a 3 anos do seu projeto - porque deseja ter certeza de que não esquece nada.
fonte
Se você nunca cometer erros, não precisará realmente de testes. A maioria dos desenvolvedores comete erros, mas se você nunca cometer e está confiante de que nunca cometerá erros no futuro (e você é o único no projeto), não há realmente nenhuma razão para perder tempo escrevendo testes.
Mas sua solução está na metade do caminho, porque você propõe escrever testes ao alterar o código, mas, ao mesmo tempo, seu método assume que você nunca cometerá erros ao decidir em quais partes do código escrever testes. Isso só funciona se você sempre entender perfeitamente quais áreas uma alteração pode afetar. Eu acho que muitos desenvolvedores comuns (não você, é claro!) Experimentaram fazer uma alteração e, em seguida, um teste em algum lugar inesperado falha, porque você cometeu um erro.
É claro que uma boa arquitetura, os princípios do SOLID etc. devem impedir que isso aconteça, mas a maioria dos desenvolvedores não é perfeita, e é por isso que os testes em todo o sistema são valiosos.
fonte