Perguntas populares do desenvolvedor sobre testes

Este artigo não é um guia teórico para escrever testes e não instruções sobre o uso de ferramentas em uma pilha específica, mas uma série de perguntas populares, às vezes até muitas que não foram formadas, para as quais tentarei dar respostas. A fonte dessas perguntas são colegas, pessoas de ambos os lados nas entrevistas e conhecidos, e as respostas serão subjetivas, curtas e não exaustivas, com base nos materiais de outras pessoas e em suas experiências. O público-alvo do artigo são desenvolvedores que escrevem com certo sucesso, ou pelo menos tentam escrever testes, mas têm certas dificuldades em escrevê-los.


Tentei não me apegar a uma linguagem específica para aumentar o alcance dos leitores, mas farei uma reserva imediatamente de que trabalho no ecossistema PHP usando PHPUnit e, portanto, algumas das minhas conclusões podem não ser adequadas para outros ecossistemas. Ao selecionar perguntas e escrever, concentrei-me em muitos relatórios e artigos e os usei como referência.


A razão para escrever foi o recente artigo “ PHPUnit. Wretting the Doctrine Entity Manager "por arrasto , alguns dos quais discutirei também.


Lista de perguntas:


  • Escrever ou não escrever testes?
  • E se o tempo não for alocado para testes?
  • Tipos de teste, como escolher?
  • Por que é difícil escrever testes por um longo tempo?
  • Como testar métodos privados?
  • Como escrever testes de integração? Como testar a base?
  • Como: integração ou funcional?
  • O que fazer com dependências externas?
  • Como simplificar a navegação entre testes e assunto do teste?
  • Devo usar TDD?
  • O que mais pode ser usado para melhorar o código?

Escrever ou não escrever testes?


Vi muitas opiniões sobre esse assunto, mas vim por conta própria: preciso me concentrar nas necessidades dos negócios.


Para um pedaço de código feito em algumas horas no joelho, os testes não são necessários. Por outro lado, para um grande projeto corporativo para centenas de recursos humanos, todos os tipos populares de testes são necessários. E tudo o que há entre esses pólos deve ser considerado como um caso especial, avaliando o custo de certos tipos de testes: com testes, deve ser menor do que sem eles. Pessoalmente, escrevo testes de fumaça mesmo para um projeto CRUD minúsculo que dura algumas semanas, porque já a essa distância eles trazem benefícios e reduzem o custo de desenvolvimento.


Vantagens de testar, resumidamente e abstratamente:


  • Uma redução significativa no custo de correção de um bug devido à detecção precoce.
  • Contratos de fixação.
  • Documentação de baixo nível.
  • Detecção de problemas de arquitetura.

Portanto, se seus projetos não são scripts únicos de vários arquivos, eu definitivamente recomendo a criação de testes. Portanto, a pergunta do título deve ser reformulada: "Até que ponto os testes devem ser escritos e quais?" Sobre isso mais.


E se o tempo não for alocado para testes?


Esta é uma questão muito controversa, por isso farei uma reserva mais uma vez que estou falando exclusivamente sobre minha opinião subjetiva, enquanto tento fazer isso da maneira mais delicada possível.


Escrever testes é tão uma tarefa quanto pensar, codificar ou depurar. Os testes são do mesmo código da lógica de negócios ou dos controladores. Mas você tem alguma dúvida sobre eles? Você não define uma tarefa separada para escrever um controlador e não o coordena com os gerentes?


Não é necessário dedicar tempo adicional para escrever testes de unidade e integração. Os testes são escritos como parte da tarefa principal. O líder técnico do projeto, como o proprietário do repositório do projeto e uma pessoa competente, decide como, o que e com que cobertura os testes devem ser escritos, concentrando-se nas tarefas do negócio, não inflando, mas reduzindo o custo de desenvolvimento.


No entanto, pode acontecer que o cliente não acredite em testes e acredite que, com a ajuda deles, você não economiza, mas apenas perde tempo. Ele paga dinheiro e define condições, com o mesmo sucesso que pode proibir que você use um tema sombrio no seu IDE ou para usar cinco espaços como recuo. E se as condições não forem discutidas ou a discussão estiver em um impasse, sua escolha é aceitar essas condições ou recusar. Com consequências de aconselhamento.


Farei uma reserva de que o último é verdadeiro apenas se você puder escrever testes, avaliar adequadamente os custos deles e o retorno estimado. Se você quer aprender a escrevê-las às custas do empregador em um projeto de curto prazo, e ele é contra, então estou do lado dele.


Tipos de teste, como escolher?


Michael Cohen Testing Pyramid


Você pode olhar para a pirâmide de teste de Mike Cohen: como desenvolvedores, estamos interessados ​​nos dois níveis mais baixos de teste. O esforço máximo deve ser dado ao teste de unidade, é o mais barato (por baixo preço, quero dizer o tempo gasto em desenvolvimento e suporte), esses testes são muito simples de implementar, muito simples de executar, funcionam rapidamente.


Mas o teste de unidade é sempre aplicável ou aconselhável? Acredito que, para o CRUD primitivo, esses testes levem muito tempo com pouco impacto e não garantam nada. Tente testar o repositório (Repository in DataMapper) e, em seguida, responda à pergunta, o que ele nos deu. Mas para uma variedade de calculadoras, essa abordagem será ideal.


Sempre tente escrever testes de unidade sempre que possível, mas não teste o que é inútil testar.


Como testar o trabalho conjunto de back-end e front-end, se houver projetos diferentes em pilhas diferentes? Assim como o back-end e o aplicativo móvel: trata-se de um teste do sistema e deve ser do interesse dos engenheiros de QA e DevOps, não dos desenvolvedores (bem, apenas se você não tiver um scrum real e impiedoso, onde a única função disponível é um desenvolvedor de pilha completa).


Além disso, o teste do sistema é o mais caro em termos de desenvolvimento e suporte, tanto em tempo quanto em infraestrutura. A solução dos problemas relacionados a isso já está fora da competência dos desenvolvedores "lineares" e a questão de sua aplicação e volumes deve ser decidida pelo diretor técnico e pelos líderes das áreas, juntamente com o negócio.


Por que é difícil escrever testes por um longo tempo?


Às vezes, é difícil escrever testes porque o código não está pronto para eles. Uma pilha de multidões, onde alguns deles dão a outros, também são uma consequência.


Não use registros, singletones, localizadores, pois isso complica muito sua vida. Esta foi a principal reivindicação do artigo a que me referi acima. Use o DI e implemente os repositórios necessários nos serviços imediatamente. Observe a lei de Deméter para evitar cadeias de mokas. Tente um pouco de trabalho usando a metodologia TDD.


Trate os testes como código de primeira classe, observando o mesmo código de alta qualidade da lógica de negócios. A má qualidade do código de teste reduzirá a produtividade ao longo do tempo.


Como testar métodos privados?


De jeito nenhum. Estamos testando um contrato - a interface fornecida pelo módulo para outros módulos. Não precisamos testar a implementação interna, ela pode mudar.


E se houver alguma lógica complicada dentro do teste e testar o contrato se transformar em uma grande quantidade de informações, onde algo estranho acontece dentro? É necessário refatorar o código, distribuindo-o em diferentes classes, onde esses métodos privados se tornarão públicos, eles já escrevem testes de unidade. E se não houvesse testes, esses lugares seriam difíceis de detectar, o que aumentaria o custo do suporte a esse código.


Como escrever testes de integração? Como testar a base?


Use acessórios. Explore ferramentas populares na sua pilha.
Não escreva pacotes universais grandes de acessórios, use seu número mínimo. Se você precisar de um determinado estado de objetos para seus testes, não reutilize esses equipamentos em outros locais onde esse estado não é necessário; caso contrário, o suporte ao teste se tornará mais complicado: alterá-los para alguns testes interromperá outros e exigirá tempo adicional.


Existem testes de integração que não passam por um ciclo completo da solicitação à resposta, e a interação das classes é verificada apenas dentro do componente. Se eles não tiverem trabalho direto com o banco de dados, você poderá criar um conjunto de dados e / ou mok que serão inseridos na entrada. Nesses casos, você pode evitar o uso de acessórios e reduzir a complexidade e o tempo de execução desses testes de integração para o nível modular.


Como: integração ou funcional?


O teste de integração é um dos níveis de teste em termos de isolamento. Teste funcional - teste de conformidade. Essas definições estão em planos diferentes, e você não pode colocar um sinal de igual entre eles, mas, na prática, nas conversas entre desenvolvedores, elas significam a mesma coisa, embora isso não esteja correto.


O que fazer com dependências externas?


Substituímos dependências externas por moki. Não apenas para testes de unidade, mas também para testes de integração.


Por exemplo, usamos o cliente HTTPS para acessar alguma API através da classe Guzzle. Se você criar uma instância dessa classe dentro da classe testada, será difícil substituí-la, mas a solução será muito simples: implementamos esse cliente no construtor e, durante o teste, substituímos por um moch.


Como simplificar a navegação entre testes e assunto do teste?


As ferramentas de desenvolvimento modernas podem rastrear a localização dos testes ou classes de teste se você usar padrões de nomenclatura. Para facilitar a navegação, você pode usar a combinação de teclas Ctrl + Shift + T nos produtos JetBrains. Além disso, se o teste não existir, você será solicitado a criá-lo e criar uma estrutura de arame.


Às vezes, você precisa de várias classes ou métodos de teste diferentes para o assunto do teste; nesse caso, você precisa ajudar o IDE, por exemplo, adicionar a anotação @covers no caso do PHPUnit.


Devo usar TDD?


O TDD é uma das metodologias de desenvolvimento nas quais iterativa e necessariamente escreve primeiro os testes e depois o código. Definitivamente, vale a pena experimentá-lo, ele ensinará como escrever código bem testado. No entanto, essa abordagem não foi amplamente utilizada, tem problemas. Um desses problemas é que você escreve testes que não escreveria com a abordagem clássica. E esses testes também precisam ser suportados, gastando tempo com isso, e o benefício deles é pequeno. Por exemplo, testes para setters ou testes para classes em que nada acontece, exceto chamadas de dependência. Esses locais são melhor verificados pelo teste de integração.


O que mais pode ser usado para melhorar o código?


As ferramentas de análise estática são outra maneira de melhorar a qualidade do seu código. Eles se sobrepõem parcialmente aos testes pelo resultado, mas geralmente descobrem que os testes não foram encontrados, especialmente com baixa cobertura. Sua vantagem indiscutível - você vê o resultado imediatamente no IDE e obtém feedback instantaneamente.


Isso não significa que é suficiente deixá-los apenas no IDE; é altamente recomendável usá-los no IC para ver possíveis erros e não estragar esse código.
Também recomendo adicionar o suporte da ferramenta de verificação de estilo de código ao IDE e ao CI. Os erros geralmente são ocultados entre códigos escritos descuidadamente e essas ferramentas permitem encontrar essas áreas.


Materiais para estudos adicionais


Source: https://habr.com/ru/post/pt462551/


All Articles