Não seria benéfico escrever testes durante a revisão de código?

24

Um colega meu teve uma ideia que achei interessante.

Não seria vantajoso escrever testes durante a revisão de código, pela pessoa que faz a revisão assumindo que não fazemos TDD?

Para esta questão, suponha que este seja um projeto puramente acadêmico, para que não haja vida em jogo. Além disso, a equipe é de 4 pessoas. Todo mundo conhece a linguagem e está familiarizado com todas as ferramentas / bibliotecas / estruturas usadas e pode escrever testes. Então, basicamente, pessoas que não são engenheiros ninjas líderes seniores, mas codificadores decentes.

Profissionais que encontrei:

  1. Incentiva uma compreensão mais profunda do código durante a revisão para escrever testes significativos.
  2. Em seguida, você pode adicionar uma revisão de código dos testes realizados pelo autor do código que está sendo testado.

Contras que encontrei:

  1. O ciclo de feedback entre a escrita e o teste do código aumenta.

Edição: Eu sei que não vai funcionar bem em aplicativos da web "normais". O que eu tinha em mente era um caso de esquina em que você implementa algoritmos científicos complexos que exigem cuidados com os detalhes. Vamos supor algo como implementar minha própria biblioteca de gráficos, PNL, etc. Gostaria de saber se o código que estamos escrevendo é isolado dos bancos de dados e é muito difícil de compreender, não seria o nível adicional de controle, a outra pessoa que precisa entender a fonte codifique e faça testes significativos, torne todo o processo menos propenso a esses bugs menos óbvios que não travam o aplicativo, mas acabam fazendo com que seus resultados sejam um lixo.

Sok Pomaranczowy
fonte
3
Você não menciona se essa série de testes estaria acima dos testes que deveriam ocorrer durante o desenvolvimento ou no lugar de.
Robbie Dee #
3
Seria benéfico, mas bastante difícil, escrever unittest (isolamento de testes) se "não fizermos TDD" porque o código não tdd é geralmente difícil de isolar. Os testes de aceitação de escrita e / ou teste de integração também serão diferenciados e / ou frágeis se você não tiver uma camada de abstração de banco de dados (API do repositório) que permita definir pré-condições reproduzíveis e não frágeis.
K3b
4
@JoulinRouge: TDD ajuda com isso. Como não há código, você não pode adaptar o teste ao seu código.
Jörg W Mittag
6
Parece que seria uma revisão de código REALMENTE longa.
David diz Restabelecer Monica
2
Eu trabalhei em locais onde uma revisão por pares envolveu um colega programador examinando todas as linhas que você escreveu, comparando-as com as diretrizes de estilo e as melhores práticas e escrevendo os testes de unidade que você não pensou em escrever.
Candied_orange 10/05

Respostas:

7

Não seria benéfico escrever testes durante a revisão de código pela pessoa que a fez?

Descobri que um bom momento para escrever testes é quando você percebe que precisa de um teste para uma situação.

A troca de tarefas para computadores é cara - ainda mais para os humanos.

Neste momento, você geralmente tem um bom entendimento dos requisitos e dependências para o teste. Portanto, aproveite a imersão da sua equipe no problema. Se precisar refinar seu novo teste no futuro, ótimo, você já possui a estrutura / acessórios de teste e tudo o que você precisa fazer é mudar a parte que precisa ser aprimorada.

Se isso acontecer durante a revisão do código, por que não fazer isso? Eu já fiz isso antes. Descobri que é melhor do que não, especialmente se você pode fazê-lo rapidamente, e ainda melhor se não o fizesse de outra forma.

Supondo que não fazemos TDD?

Mesmo se você pratica TDD, se percebe que precisa de um teste enquanto faz a revisão de código, que você não possui, por que não escrever o teste naquele momento?

Prós

  • Você aproveita seu foco no código em revisão.
  • Às vezes, a revisão de código se torna o ponto de encontro e o tempo de bate-papo quando as pessoas não participam. Escrever um teste incentiva todos a pensar mais ativamente sobre o código que está sendo revisado.
  • Mais membros juniores da equipe terão a oportunidade de aprender com a experiência de escrever testes.
  • Você pode identificar talentos em sua equipe que não sabia que tinha.

É realmente um engodo que mais testes possam levar a mais código? Se o teste foi necessário, e o código foi necessário para o teste, e agora você o possui, isso é uma coisa boa .

Ressalvas

Talvez parte da equipe precise se concentrar em outras coisas. Se isso causa uma distração das prioridades ou a revisão do código excede o cronograma, é necessário limitar ou cortar a gravação real do teste. No entanto, a revisão de código certamente pode identificar testes que precisam ser gravados, e talvez eles possam pelo menos ser descartados para o escritor concluir posteriormente.

Aaron Hall
fonte
22

Esta é uma ideia maravilhosa, com uma ressalva. Não substitua testes escritos pelo desenvolvedor por testes escritos pelo revisor. Peça aos seus revisores que procurem casos de canto e entradas que quebrem o código. Em outras palavras, peça que eles tentem escrever novos testes que o desenvolvedor original não pensou em escrever.

Escrever testes de caracterização é uma maneira absolutamente maravilhosa de entender um pedaço de código que você não escreveu. Fazer com que seus revisores realizem testes adicionais no código, oferece a eles uma compreensão muito melhor de como o código funciona, como pode ser quebrado e como pode ser aprimorado. O tempo todo, aumentando sua cobertura de código.

Todas essas são vitórias no meu livro.

Pato de borracha
fonte
5
É quase como se você tiver o código de revisão experiência ...
syb0rg
Não faço ideia do que você está falando @ syb0rg ... Você não pode provar isso. =;) -
RubberDuck
2
tosse ;-)
Mathieu Guindon
2
Além disso, um caso de teste é apenas sobre a maneira menos ambígua de descrever uma falha descoberta em revista :-)
Steve Jessop
11
@ syb0rg O Rubber Duck ajudou milhares ou milhões de programadores a corrigir seu código . Quem está mais qualificado para revisar o código do que quem já viu tanto?
Jpmc26
18

Eu não acho que a idéia seja totalmente sem mérito - no entanto, o principal benefício do TDD et al é que os problemas são encontrados cedo . O desenvolvedor também está em melhor posição para identificar quais casos de canto podem exigir atenção específica. Se isso for deixado até a revisão do código, há um risco de que esse conhecimento possa ser perdido.

Escrever testes durante a revisão de código sofreria o mesmo problema que os testes manuais tradicionais - o entendimento das regras de negócios pode variar de desenvolvedor para desenvolvedor, assim como a diligência.

Há também a discussão antiga que será executada e executada para determinar se os desenvolvedores testariam seu código tão bem se soubessem que havia uma função de teste mais à montante que deveria detectar os bugs mais sérios.

Robbie Dee
fonte
Ótima resposta. Mas e se não fizermos TDD porque as pessoas não querem e eu não tenho influência sobre elas, mas precisamos garantir que o resultado obtido não seja falso positivo, porque um erro distorceu nossos resultados? O principal risco é que as pessoas se apressem em implementar algo sem o entendimento adequado, escrevam testes com esse entendimento impróprio, fazendo com que os testes passem, mas acabem produzindo código errado. Talvez a programação em pares resolvesse o problema? Mas, novamente, é fácil forçar a compreensão de algo sobre alguém.
Sok Pomaranczowy
Acho que talvez, assim como alguém escrevendo os testes, eles possam ser executados no código de desenvolvimento enquanto o desenvolvimento estiver em andamento. Os desenvolvedores em questão precisariam estar na mesma página em que o código está; caso contrário, o desenvolvedor que escrever o código poderá estar constantemente testando falhas no combate a incêndios, em vez de realmente fazer a coisa funcionar.
Robbie Dee #
O problema é chamado de "Viés Conformacional".
Artes
Na verdade, eu diria que, distraído do processo de revisão de código, o código afetaria o processo de teste, que não é o que você deseja, tirando a principal vantagem de ter um testador e codificador separados.
Artes
11
@RobbieDee Se o destinatário da culpa realmente importa, você tem um ambiente de desenvolvimento prejudicial. Isso é muito pior do que perder alguns testes que teriam sido úteis.
Jpmc26
5

Concordo com a resposta de @ RobbieDee, mas tenho um pouco mais a acrescentar.

Se você realmente gosta dessa ideia, por que não as mesmas pessoas escrevem os testes antes do código como critérios de aceitação executável para a história do usuário?

Isso faria a mesma coisa, ainda manteria o feedback curto e levaria todos a ter uma discussão sobre a história, o que acho que seria de maior valor.

As desvantagens são o risco de uma reunião interminável de critérios de aceitação :-( e eu acho que você está tentando convencer as pessoas na revisão de código a dar uma olhada no código de implementação, mas eu sugeriria programação de pares e pares rotativos como uma solução melhor para Esse problema.

O OP adicionou uma edição na qual eles detalham mais detalhes sobre esse recurso difícil ou pesado de algoritmo.

Em resposta a isso, acrescentaria que o seu instinto de obter mais olhos no problema e na solução é bom. Talvez emparelhe com várias pessoas, uma a uma, até que todos tenham visto a parte realmente difícil dos códigos e testes de implementação. Cada um lançando novas idéias e agregando mais valor.

Às vezes, há uma idéia chamada programação mob, como emparelhamento, mas com mais pessoas. Isso é quase do que você está falando, mas eles ajudam no momento da redação e não em uma revisão formal depois. Isso não é para todos, e pode exigir um driver forte (líder) para fazê-lo funcionar, ou uma equipe que se sinta muito confortável entre si e com o processo.

Fazendo o que aconteceu depois da programação da multidão, eu acho que teria muitas das mesmas vantagens de muitos olhos vendo o problema e sugerindo melhorias e se é assim que sua equipe está confortável em operar, isso pode ajudar, mas eu realmente tentaria manter o necessário ocorrências disso ao mínimo, pois acho que isso pode atrasar a equipe.

Encaitar
fonte
Talvez os desenvolvedores devam escrever testes como acharem conveniente, enviá-los para o repositório, mas a pessoa que faz a revisão deve escrever seus próprios testes e nunca olhar para os testes que o desenvolvedor escreveu. Se os dois conjuntos de testes passarem bem, mas se os testes do revisor falharem, pode haver um problema?
Sok Pomaranczowy
11
@SokPomaranczowy adicionar redundância em testes de escrita de diferentes pessoas foi tentado no passado. Acho que se você não está desenvolvendo software crítico para a vida, isso é um desperdício de esforço. Em vez disso, você deve se concentrar em onde é melhor gastar seu tempo (você nunca escreverá TODOS os testes) e com boa comunicação na equipe. é uma abordagem muito melhor.
Encaitar
@ Encaitar Eu concordo, isso soa como um enorme coletor de tempo que provavelmente não tornará as coisas muito melhores. RoI e tudo isso ...
sara
3

Como você diz, se você estiver executando uma equipe de TDD, isso é discutível, já que o código já deve ser testado.

No geral, não acho que essa seja uma ótima idéia, mas depende da sua abordagem atual e do que funciona para você. Basicamente, o problema que vejo é que você perde a vantagem do "curto ciclo de feedback" dos testes. Receber notificação instantânea no momento em que você quebra algo, enquanto escreve um novo código, é onde os testes realmente brilham. Se você adiar o teste até a revisão do código, estará basicamente dizendo "bem, poderíamos corrigir esse problema mais cedo em menos tempo e com menos pessoas envolvidas, mas pelo menos todos aprendemos alguma coisa (talvez)". Eu preferiria apenas garantir que as pessoas enviassem o código testado para revisão e, em seguida, você julgue a correção e a manutenção dos testes. Afinal, a revisão de código é para revisar, não para escrever código.

Por outro lado, eu recomendo que você se delicie com os testes / código durante a revisão. Tente quebrar alguma coisa. Comente uma condição if. substitua um booleano por um literal verdadeiro / falso. Veja se os testes estão falhando.

Mas sim, em suma, recomendo que você escreva seus testes junto com o seu código e depois revise tudo de uma vez.

sara
fonte
2

Depende do que você está fazendo na revisão de código. Eu acho que há duas razões principais para escrever testes nessa fase:

  • primeiro, se você também refatorar durante a revisão de código e notar que não há testes de unidade suficientes para cobrir o tipo de refatoração que você deseja aplicar, adicione esses testes

  • segundo, se o código lhe parecer ter um bug e você quiser provar (ou refutar) isso, escreva um teste para ele

Ambos os casos expressam a necessidade de testes que não existem no momento, mas deveriam existir. Obviamente, pode depender da cultura de sua equipe se esse tipo de teste deve ser escrito pelo revisor ou pelo autor original, mas alguém deve escrever os testes.

Na verdade, não acho que seja "um caso de esquina" apenas adequado para "algoritmos científicos complexos" - pelo contrário, é adequado para qualquer tipo de software do qual você espera um certo grau de qualidade.

Doc Brown
fonte
2

Não faça isso. Você os fará pensar que o TDD é horrível.

Eu acho que o @ k3b está certo nos comentários sobre a questão. O código gravado através de um processo no estilo TDD tende a parecer e interagir muito diferente do código gravado sem testes. A adição de (bons) testes ao código não testado geralmente exige muita refatoração do código para esclarecer suas intenções e partes móveis.

Ao adicionar os testes depois de escrever o código, você perde os aspectos arquitetônicos dos benefícios do TDD (que, a meu ver, são um dos principais benefícios). Além disso, você está pedindo a alguém que não esteja tão familiarizado com o código que aceite adicionar testes que já são difíceis de adicionar.

A pessoa que está adicionando testes precisará refatorar significativamente o código ou precisará trabalhar muito para testar o código não testável. De qualquer forma, eles não vão gostar da experiência. Mesmo que este não seja o TDD clássico, eles não o verão dessa maneira, e você pode colocá-los fora do TDD de uma vez por todas.

(Se você já está seguindo um processo de TDD, escrever testes adicionais durante a revisão de código seria menos prejudicial, embora, na minha experiência, se os testes já estiverem bem escritos, é igualmente fácil explicar o teste extra à pessoa que envia o código para revisão e peça que eles os escrevam.)

Andy Mortimer
fonte
1

Os testes de unidade durante a revisão de código são um mau substituto para os testes de unidade durante o desenvolvimento.

O que você está sugerindo faz muito sentido, intuitivamente. Qual é a revisão? Para verificar se o código está bom. Para que servem os testes? Para verificar se o código está bom. Então, por que não combinar os dois?

Aqui está o porquê.

Colocar o código em teste é um trabalho árduo. Escrever código que simplesmente funciona com a única coisa que deve fazer é uma coisa; escrever código que possa ser testado de maneira eficaz e eficiente é outro. Apenas o fato de o código agora ser executado em dois cenários - "trabalho real" e "teste" - exige muito mais flexibilidade, exige que esse código seja capaz de se sustentar por si próprio de maneira significativa.

Escrever seu código para que seja testável é um trabalho e habilidade extra. Refatorar o código de outra pessoa para testabilidade, quando não foi escrito com a testabilidade em mente, pode ser uma tarefa importante.

Você está duplicando o esforço entre o desenvolvedor e o revisor. Presumivelmente, seu desenvolvedor não está entregando seu código para revisão sem pelo menos algum nível de confiança de que está funcionando. Ele já precisa testar o código. Agora, existem diferentes níveis e escopos de teste. O controle de qualidade testa o código após o desenvolvedor e o revisor. Mas qualquer que seja o escopo que você considere apropriado para o desenvolvedor e o revisor, não faz sentido para o desenvolvedor descobrir como testar o código nesse nível uma vez , mas torne seus testes descartáveis ​​e difíceis de reproduzir e, em seguida, leve o revisor para desenvolver teste novamente, desta vez automatizados e reproduzíveis. Você está apenas fazendo com que ambos invistam tempo escrevendo os mesmos testes - uma vez mal, outra bem.

Você está transformando a revisão em uma etapa muito mais longa e trabalhosa. Se o teste é uma parte importante do processo de revisão, o que acontece quando alguns testes falham ? O revisor é responsável por executar todos os testes e, portanto, também precisa depurar o código? Ou será um pingue-pongue de um lado para o outro, um escrevendo testes, o outro fazendo com que eles passem?

Às vezes, você pode escrever vários testes ortogonais entre si, para não precisar de ping-pong. O revisor escreve uma dúzia de testes, metade deles falha, o desenvolvedor corrige os bugs e todos os testes permanecem válidos e passam agora. Mas ... na maioria das vezes, você tem bugs de bloqueadores, ou que exigem alterações de redesenho e API, ou outros enfeites. Se você está assumindo a responsabilidade de passar nos testes entre o revisor e o desenvolvedor, não está realmente na fase de revisão. Você ainda está desenvolvendo.

A necessidade de escrever testes não incentiva uma revisão mais completa. Basicamente, significa que, quanto mais fundo você vai, mais testes você precisa escrever e provavelmente serão testes difíceis que precisam se aprofundar no sistema.

Compare com o desenvolvedor que está escrevendo os testes, onde está seu incentivo: se eu não escrever testes importantes, o revisor indicará isso na revisão.

Mesmo o revisor terá uma compreensão muito melhor do sistema se precisar passar por testes completos do código , se precisar decidir por si próprio quando pode parar de escrever o teste de escavação profunda e apenas fazer a revisão do código.

Se o desenvolvedor não estiver escrevendo testes de unidade, o revisor também não. Existem muitos obstáculos para a adoção de testes como uma prática comum. Talvez você esteja sob muita pressão e seja difícil colocar sua base de código em teste. Talvez você não seja tão experiente em testes e sinta que não pode pagar a curva de aprendizado. Talvez você tenha um assassino em machado enviando notas ameaçadoras para as pessoas que fazem testes. Eu não sei!

Seja qual for a causa, é seguro apostar que se aplica igualmente ao revisor e ao desenvolvedor. Se a equipe está estressada, o revisor não tem mais tempo do que o desenvolvedor (se tiver, redistribua o trabalho para que as pessoas não fiquem tão estressadas ). Se ninguém souber escrever bem os testes de unidade, o revisor provavelmente também não (se souber, deve sentar-se e ensinar aos colegas de equipe ).

Essa sugestão parece tentar passar a bola de um colega para outro. E eu simplesmente não vejo nenhuma maneira de isso dar certo, em primeiro lugar, porque é realmente difícil (e doentio) criar uma situação em que uma pessoa é a única que pode fazer testes e outra não pode fazer qualquer teste.


O que funciona é ter a revisão para cobrir os testes também. Se o desenvolvedor já escreveu dez testes, é muito mais provável que o revisor possa ajudar a sugerir outros dez, do que se o desenvolvedor não tivesse escrito nenhum.

E, se testar casos de esquina é uma tarefa importante, pode fazer sentido distribuí-lo mais amplamente por toda a equipe. ** Uma vez que o código é testável, escrever mais testes se torna muito mais fácil. **

A revisão é um ótimo momento para identificar casos de canto. E, se o revisor puder entrar e escrever um teste para os casos de canto que encontrar, então ei - melhor ainda! Mas de um modo geral, supondo que o revisor possa escrever testes nos quais o desenvolvedor não parece uma péssima idéia.

Standback
fonte