Tentamos introduzir testes automatizados para desenvolvedores várias vezes na minha empresa. Nossa equipe de controle de qualidade usa o Selenium para automatizar testes de interface do usuário, mas eu sempre quis apresentar testes de unidade e testes de integração. No passado, cada vez que tentávamos, todo mundo ficava empolgado pelo primeiro ou dois meses. Então, vários meses depois, as pessoas simplesmente param de fazer isso.
Algumas observações e perguntas:
O teste automatizado realmente funciona? A maioria dos meus colegas que trabalhavam em outras empresas tentou e falhou ao implementar uma estratégia de teste automatizada. Eu ainda não vi uma empresa de software da vida real que realmente o usa e não fala apenas sobre isso. Muitos desenvolvedores veem os testes automatizados como algo ótimo em teoria, mas que não funciona na realidade. Nossa equipe de negócios adoraria que os desenvolvedores fizessem isso mesmo a um custo de 30% de tempo extra (pelo menos assim o dizem). Mas os desenvolvedores são céticos.
Ninguém realmente sabe como fazer testes automatizados corretamente. Sim, todos nós lemos os exemplos de testes de unidade na internet, mas usá-los para um grande projeto é algo completamente diferente. O principal culpado é zombar / stubbing do banco de dados ou qualquer outra coisa que não seja trivial. Você acaba gastando mais tempo zombando do que escrevendo testes reais. Então, quando começa a demorar mais tempo para escrever testes do que o código, é quando você desiste.
Existem bons exemplos de testes de unidade / testes de integração de sistemas usados em aplicativos da Web complexos e centrados em dados? Algum projeto de código aberto? Nossa aplicação é centrada em dados, mas também possui muita lógica de domínio. Eu tentei a abordagem de repositório em algum momento e achei muito bom para testes de unidade, mas teve o preço de otimizar o acesso a dados facilmente e adicionou outra camada de complexidade.
Temos um grande projeto realizado por 20 desenvolvedores experientes. Este parece ser o ambiente ideal para introduzir testes de unidade / testes de integração.
Por que isso não funciona para nós? Como você fez isso funcionar na sua empresa?
fonte
Respostas:
A parte mais difícil de fazer o teste de unidade é conseguir a disciplina para escrever testes primeiro / mais cedo. A maioria dos desenvolvedores está acostumada a apenas mergulhar no código. Também atrasa o processo de desenvolvimento desde o início, enquanto você tenta descobrir como escrever um teste para o código. No entanto, à medida que você melhora nos testes, isso acelera. E por causa dos testes de escrita, a qualidade inicial do código começa mais alto.
Ao iniciar, tente apenas escrever testes. Não se preocupe tanto com zombarias / stubbing no começo. Mantenha os testes simples. Os testes são de código e podem / devem ser refatorados. Embora nesse sentido, se algo for difícil de testar, também possa ser o design. O TDD se esforça para usar a maioria dos padrões de design (na minha experiência, particularmente o padrão de fábrica).
Certifique-se de que os testes obtenham um nível de visibilidade. Integre-os no processo de lançamento, durante a revisão do código, pergunte sobre eles. Qualquer erro encontrado deve ser testado. É nessas coisas que o TDD brilha.
Aqui estão alguns recursos que eu achei úteis:
http://misko.hevery.com/attachments/Guide-Writing%20Testable%20Code.pdf
http://www.agitar.com/downloads/TheWayOfTestivus.pdf
Editar:
Uma coisa a ter em mente quando você está escrevendo testes. Você não está tentando especificar nada sobre a implementação do código, apenas o comportamento. Quando você escreve código, você o testa o tempo todo. Tentando executá-lo com instruções de depuração e assim por diante. Escrever testes formaliza isso e fornece um registro dos testes que você possui. Dessa forma, você pode verificar sua funcionalidade com confiança, sem ignorar acidentalmente um caso de teste que você lembrou no meio do processo de desenvolvimento.
fonte
De muitas maneiras, eu concordo com sua equipe.
A maioria dos testes de unidade é questionável em valor. Como a grande maioria dos testes parece ser muito simples.
É muito mais difícil escrever um bom código testável do que apenas trabalhar código. Há uma grande porcentagem da comunidade de desenvolvedores que acredita em fazê-lo funcionar, em comparação com a qualidade do código / design em si. E uma porcentagem ainda maior que nem sabe o que é um código de qualidade.
Pode levar muito mais tempo para escrever o código do teste de unidade do que o próprio código.
Descobrir como testar adequadamente o código mais complicado (isto é, o que você realmente está interessado em testar minuciosamente) está além dos recursos de muitos desenvolvedores.
A manutenção de testes de unidade leva muito tempo. Pequenas alterações podem ter grandes efeitos de ondulação. O principal objetivo dos testes de unidade automatizados é descobrir se as alterações quebraram o código. No entanto, 99% das vezes o que acaba quebrando são os testes e não o código.
Com todos os problemas acima, ainda não há uma maneira melhor de fazer alterações no código e ter algum nível de confiança de que algo não ocorreu inesperadamente do que automatizar seus testes.
Alguns dos itens acima podem ser aliviados até certo ponto, não seguindo o livro de testes de unidade.
Muitos tipos de projetos / aplicativos são melhor testados automatizando testes no nível do módulo / pacote. Na minha experiência, a maioria dos erros de codificação não ocorre porque o código de uma classe foi codificado incorretamente, mas porque o codificador não entendeu como sua classe deveria funcionar com outras classes. Eu já vi muito estrondo neste tipo de teste. Mais uma vez, porém, esses testes são mais difíceis de escrever do que os testes de unidade (nível de classe).
Realmente se resume a se os desenvolvedores acreditam no processo ou não. Se o fizerem, eles escreverão bons testes de unidade, encontrarão os erros mais cedo e serão proponentes. Se não o fizerem, seus testes de unidade serão, em geral, inúteis e não encontrarão nenhum erro, e sua teoria de testes de unidade como inútil será comprovadamente verdadeira (em suas mentes).
O ponto principal é que eu nunca vi a abordagem de teste de unidade automatizada completa funcionar por mais de um par de meses, mas a idéia de testes de unidade automatizados ainda persiste, apesar de sermos seletivos no que realmente precisa de teste. Essa abordagem tende a ter muito menos críticas e é mais aceita por todos os desenvolvedores do que apenas alguns.
fonte
Frobinate()
método de nível superior (em vez das dezenas de métodos menores chamados abaixo) depois que o sistema foi verificado por outros meios para servir como teste de fumaça, que nenhuma das mudanças de nível inferior quebrou nada. Geralmente esses testes usavam os mesmos dados que faziam parte da libra nos testes do usuário do teclado, fornecidos para que o cliente possa ver que o sistema está fazendo o que deseja. Posteriormente, as ferramentas de cobertura de código podem identificar onde casos extremos ainda não estão sendo cobertos.E aí está o seu problema.
Todo mundo faz boas observações sobre como integrar o teste de unidade ao seu ambiente. Como forçar as pessoas a fazê-lo o suficiente para que vejam o valor prático e ele "adira". Mas se é super doloroso de fazer e / ou não oferece nenhum benefício, ele não ficará.
A remoção de um banco de dados deve ser simples. Em vez de sua interface recorrer a algum suporte de banco de dados para fornecer seus resultados, você coloca um objeto codificado simples. Se você não pode fazer isso, seu design / arquitetura tem problemas. Seu código assume que está indo para um banco de dados ou você não tem a abstração da interface para variar.
Isso não é apenas uma preocupação de teste / qualidade. Assim que você deseja alterar os provedores de banco de dados, ou ir para a nuvem, ou oferecer suporte a aplicativos móveis não conectados, seu design simplesmente falha. Se você não pode suportar os casos mais simples de flexibilidade, certamente não pode suportar as coisas mais complexas que sua empresa inevitavelmente exigirá.
fonte
Você precisa começar com algo pequeno, simples de automatizar e de alto valor. Puxe algumas frutas doces e baixas, e você poderá vender o processo. Mostre como ele salvou alguém tarde da noite ou uma ligação de fim de semana. Então você pode expandir a partir daí.
Para executar bem os testes automatizados, você precisa de alguém que seja um recurso e um evangelista, e que tenha participado de gerências de nível superior.
Trate seu desenvolvimento automatizado de testes como qualquer outro projeto ágil. Produza testes concluídos regularmente.
Adicionando do comentário: Esse é mais um problema de gerenciamento. O código é considerado "concluído" antes de ser documentado? Antes de fazer o check-in? Antes de incluir e passar nos testes de unidade?
Como você aborda isso realmente depende do seu papel. Você é um colega? Nesse caso, mostre aos outros como isso facilita seu código para reutilizar e manter. Você é um líder? Escolha seu programador que tem mais problemas de código e ajude-o a adicionar testes para evitar esses problemas. Você é um chefe? Defina como padrão que "o código não é feito até que os testes de unidade estejam chegando e passando.
fonte
Siga estas regras básicas. Testes:
deve executar regularmente! Você pode executar testes em todas as versões, antes / depois de cada check-in ou apenas todas as manhãs. O acionamento automático é altamente preferível ao acionado manualmente. Porque, embora em teoria você possa ser responsável por garantir que todos executem testes, se não for automatizado, provavelmente não acontecerá com bastante frequência! E se você não executar seus testes com frequência suficiente, os dois encontrarão os erros tarde demais, incentivando muitos testes interrompidos, o que leva ao ponto 2:
Você ainda terá sucesso se esses testes, agora em execução regularmente, não atrapalharem . Com o que entendemos testes:
uma. não deve demorar muito para ser executado (subjetivamente) pelo valor que eles fornecem! Faça seus testes muito rápido. Não permita que as pessoas façam check-in em testes que serão uma perda de tempo para deixá-los executar!
b. não deve ser confiável. Evite testes multithread, se possível. Aplique práticas de engenharia aos seus testes, assim como seu outro código: particularmente - revise o código dos seus testes!
c. não deve ser mais difícil de corrigir e manter do que o código real testado. Sua velocidade de codificação realmente será péssima se uma linha minúscula mudar para sua base de código exigir que você faça 10 testes diferentes.
E finalmente, regra número 3. Os testes não devem apenas falhar em fornecer valor negativo, como na regra 2, eles devem fornecer valor positivo. Testes ...
Uma maneira popular de violar a regra 3 é testar a coisa errada . Às vezes, isso ocorre porque um teste é muito grande ou muito fora de foco. Mas, geralmente, resulta de não testar algo com o qual o cliente se preocupa e testar detalhes irrelevantes da implementação. (Mas, às vezes, testar os detalhes da implementação também faz um teste eficiente - na IMO, é necessário praticar o processo de decidir qual.)
Conclusão: essas regras básicas apontam você na direção geral de uma disciplina de teste sustentável , que é o que você deseja desesperadamente. Ao testar, pergunte a si mesmo se esse teste é realmente sustentável e sustentável. Lembrar:
Testar é realmente difícil. Você deve esperar que os testes de sua equipe sejam basicamente ruins quando você começar a escrever testes . Não desanime. Não jogue fora os testes antigos, sempre que notar que sugam e são insustentáveis.
fonte
Sim, sim - se feito corretamente. O ponto é que os testadores precisam ajustar e estender seus scripts automatizados depois que os engenheiros implementam novos recursos.
Procure um consultor (alguém que saiba como é feito corretamente). Ou invista mais tempo. A alternativa é ter uma equipe de teste maior, que faça o mesmo teste manualmente (o que é propenso a erros).
Eu não os chamaria de "bons desenvolvedores experientes" se eles se recusassem a fazer testes de unidade. Existem muitos artigos excelentes sobre os benefícios positivos dos testes (testes de unidade e integração) e, no final, tudo se resume a quanto um bug custa à sua empresa . Por exemplo, trabalho em uma empresa onde a qualidade importa, portanto, os testes de unidade e integração são inevitáveis. Você pode encontrar facilmente muitos artigos, informando que apenas os testes de unidade estão reduzindo o número de bugs em 30%! (Na verdade, está na faixa de 20 a 90%, em média 30%, mas ainda é muito.)
Para fazê-lo funcionar em sua empresa, contrate um consultor ou atribua essa tarefa a um engenheiro sênior (levará um tempo para fazê-lo). E então, force todos a seguir as regras.
fonte
São muitas as razões pelas quais a introdução de testes automatizados pode falhar. Eu acho que tudo se resume ao fato de que os programadores tendem a não mudar seus hábitos de codificação e não são totalmente capazes de adotar testes de unidade.
Muitas pessoas que desejam iniciar o teste automatizado tentam apresentá-los a uma base de código existente. Eles tentarão escrever testes de integração que testam muitas funcionalidades do aplicativo existente ao mesmo tempo. Tais testes de integração são notoriamente muito difíceis e caros de manter. Conselho: introduza testes automatizados para uma nova base de código.
Testes de unidade são bons testes a serem automatizados. Tudo acima (testes de integração, testes de componentes, testes de sistema) também pode ser testado automaticamente, mas a relação custo-benefício diminui rapidamente, mais funcionalidades são testadas ao mesmo tempo. Esse efeito negativo é amplificado, se você criar esses testes com funcionalidades mal testadas por unidade. Conselho: introduza testes automatizados no nível de teste de unidade e crie testes de integração automatizados em uma base sólida de testes de unidade .
Dos pontos acima, grande parte do sucesso dos testes automatizados depende da eficácia dos testes unitários. Você tem testes de unidade eficazes se se sentir produtivo com testes de unidade. Quando as pessoas começam com o teste de unidade, elas tendem a adaptar seus códigos e hábitos de codificação existentes em testes de unidade. Ironicamente, essa é a maneira mais difícil de aprender testes de unidade. Além disso, o teste de unidade exige que você altere a maneira como codifica (por exemplo, aplicando os princípios do SOLID ). Muitos programadores logo param de escrever testes de unidade porque acham que a curva de aprendizado é muito íngreme e acham estranho envolver testes de unidade em torno de um código projetado não tão testável. Conselho: Aprenda o teste de unidade desde o início com o novo código e lide com o fato de que você precisa alterar seus hábitos de codificação.
Existem muitos outros fatores, mas eu achei que, para a maioria dos programadores, é problemático mudar sua maneira de codificar. Código escrito sem teste apenas parece diferente. Se você não conseguir compactar seu código em um design testável, provavelmente falhará ao escrever testes de unidade eficazes. Isso destrói o terreno para testes automatizados eficazes.
Eu experimentei isso sozinho e agora estou feliz em trabalhar em uma empresa que introduziu com sucesso testes automatizados. Eu poderia escrever muito mais sobre os outros fatores, mas acho que os hábitos de codificação e o teste de unidade são os mais importantes. Felizmente, existem outros que têm mais experiência do que eu e enchem os livros com seu conhecimento. Um desses livros é o Brownfield Application Development no .NET que eu realmente recomendo, pois você está usando a pilha de tecnologia da Microsoft.
fonte
Introduce automated tests on the unit test level and build automated integration tests on a solid foundation of unit tests.
+1Uma coisa que eu não vi claramente abordada nas respostas acima é que o teste de unidade é essencialmente um bem público e um custo privado. Eu escrevi um post sobre isso aqui .
O que se resume é que, embora um conjunto de testes beneficie a equipe ou um desenvolvedor individual, escrever o teste é um custo para quem o faz, na maioria das vezes.
Em resumo, a menos que a execução do teste seja aplicada de alguma forma - e as respostas acima listem várias maneiras diferentes de fazer isso - não há razão para um desenvolvedor individual fazer isso.
Em uma empresa em que trabalhei, escrever testes de unidade era uma parte necessária do fornecimento de um recurso. O novo código não era aceito, a menos que um teste de unidade fizesse parte do commit ou do novo recurso - houve breves revisões de código para cada "tarefa" que um desenvolvedor recebeu. Pode valer a pena implementar uma política semelhante no seu local de trabalho.
fonte
É interessante que o negócio seja mais pró-teste do que desenvolvedores! Parece-me que seu maior desafio será superar a resistência de seus desenvolvedores à mudança; eles precisam redefinir sua compreensão de seus trabalhos para incluir testes de unidade.
Nada pode ajudá-lo mais do que sucessos anteriores no teste de unidade para ajudar seus desenvolvedores a superar sua resistência ao escrever esses testes. Se você pressioná-los para fazer algo novo, certifique-se de pressionar primeiro por algo com uma recompensa quase garantida.
@SkipHuffman tocou nisso, mas vou dizer isso de uma vez. Algumas coisas são muito mais adequadas para testes automatizados do que outras. Para a primeira passagem, eu NÃO testaria o banco de dados ou a interface do usuário. A entrada de um banco de dados pode ser extremamente difícil de configurar e desmontar. Os testes de saída da interface do usuário tendem a ser rapidamente interrompidos pelas alterações de aparência que são completamente irrelevantes para seus testes.
O que eu chamaria de "middleware" é perfeito para testes de unidade. Código que definiu claramente as condições de entrada e saída. Se você seguir o princípio DRY (Não se repita), terá escrito algumas pequenas classes ou funções para resolver problemas recorrentes exclusivos do seu aplicativo.
O teste de unidade é uma ótima ferramenta para limitar o risco de alterar os componentes internos existentes. Escreva testes de unidade antes de alterar um componente interno que funcionou por um longo tempo. Esses testes provam que a funcionalidade atualmente em funcionamento é preservada. Quando você faz sua alteração e todos os testes de unidade são aprovados, você sabe que não quebrou nada "downstream". Se você encontrar um problema a jusante, adicione um teste de unidade para ele!
Ron Heifitz diria "resolver conflitos nos valores que as pessoas detêm, ou diminuir a diferença entre os valores que as pessoas defendem e a realidade que enfrentam. O trabalho adaptativo requer uma mudança de valores, crenças ou comportamento". Depois de superar a resistência humana à mudança, você pode se ramificar em áreas de teste mais difíceis, conforme apropriado.
fonte
Uma coisa sobre o teste automatizado é que ele exige que você escreva o código para poder ser testado. Isso não é algo ruim por si só (na verdade, é bom porque desencoraja muitas práticas que, em regra, devem ser evitadas), mas se você estiver tentando aplicar o teste de unidade ao código existente, é provável que não seja. foi escrito de forma testável.
Coisas como singletons, métodos estáticos, registros, localizadores de serviços etc. introduzem dependências que são muito difíceis de serem ridicularizadas. Violações da Lei de Demeter significam que muitas partes da sua base de código sabem muito sobre como outras partes da sua base de código funcionam, introduzindo outras dependências ocultas que podem ser difíceis de quebrar. Todas essas coisas dificultam o isolamento de um módulo do restante da base de código e, se você não pode testar seus módulos isoladamente, os testes de unidade perdem muito valor. Se um teste falha, é devido a uma falha na unidade em teste, ou devido a uma falha em uma de suas dependências, ou talvez seja porque os dados que estão sendo puxados por uma fonte de dados dependente não são o que o gravador de teste esperava. ? Se você puder'
A maioria das bases de código que vi que não foram criadas com o teste de unidade em mente tendem a ser intrinsecamente testáveis, pois os codificadores tendem a se concentrar em fazer o código funcionar da maneira que esperam, em vez de fazer o trabalho necessário para manter o acoplamento solto e as dependências explícitas . O código que foi escrito com o teste de unidade em mente tende a parecer muito diferente.
Muitas pessoas adotam uma abordagem ingênua ao teste de unidade quando começam a fazê-lo pela primeira vez; pensam que podem simplesmente escrever uma carga de testes para uma base de código existente e tudo será bom, mas nunca funciona dessa maneira por causa de as questões acima mencionadas. Eles começam a descobrir que precisam de quantidades excessivas de configurações em testes de unidade para executá-los, e os resultados geralmente são questionáveis porque a falta de isolamento no código significa que você não pode rastrear o que causou uma falha no teste. Eles também tendem a começar a escrever testes "inteligentes" que demonstram algum aspecto altamente abstrato de como o sistema deve funcionar. Isso tende a falhar porque um teste de unidade "inteligente" é uma fonte potencial de bugs em si. O teste falhou devido a um erro no módulo testado, ou por causa de um bug no teste? Um teste deve ser tão torturante simples que obviamente não há possibilidade de um bug estar escondido nele. De fato, os melhores testes raramente têm mais de duas linhas, a primeira instruindo a unidade sob teste a fazer alguma coisa, a segunda afirmando que o que fez foi o que era esperado.
Se sua equipe leva a sério a adoção de testes de unidade, seria imprudente começar com um projeto existente. Os projetos existentes da sua equipe provavelmente não podem ser testados sem grandes refatorações. É melhor usar um novo projeto como base para aprender sobre testes de unidade, pois você tem uma lista limpa para trabalhar. Você pode projetar a nova base de código para favorecer a injeção de dependência em relação a singletons, registros e outras dependências ocultas. Você pode escrevê-lo para depender de interfaces, em vez de implementações e assim por diante. Você também pode (e deve) escrever os testes ao lado do código que está sendo testado, pois escrever os testes posteriormente resulta em testes de unidade que garantem que o módulo testado faça o que você pensa que deve ser feito, em vez daqueles que testam o que ele faz. o que as especificações dizem que deve fazer.
Depois de ganhar alguma confiança com o teste de unidade, sua equipe provavelmente começará a perceber as falhas no código existente que serão obstáculos aos testes de unidade. É quando você pode começar a trabalhar para refatorar o código existente para torná-lo mais testável. Não seja ambicioso e tente fazer isso tudo de uma só vez, ou tente substituir um sistema que funcione com um sistema totalmente novo, basta encontrar os bits da base de código que podem ser facilmente testados (os que não possuem quaisquer dependências ou onde as dependências sejam óbvias) e escreva testes para elas. Eu sei que disse que escrever um teste ao lado do código é preferível a escrever testes depois, mas mesmo um teste gravado posteriormente ainda tem valor como ponto de partida. Escreva os testes como se não soubesse nada sobre como a classe funciona, a não ser o que suas especificações dizem que deve fazer. Quando você executa os testes e obtém falhas, as especificações ou a implementação estão incorretas. Verifique duas vezes para determinar qual está errado e atualize o teste ou o código de acordo.
Depois de colher os frutos mais baixos, seu verdadeiro trabalho começa. Você precisa começar a encontrar as dependências ocultas na sua base de código e corrigi-las, uma de cada vez. Não fique ambicioso demais neste momento, continue fazendo um módulo de cada vez, ou mesmo apenas um problema em um módulo, até que os obstáculos aos testes sejam corrigidos e você possa passar para o próximo.
TL: DR: A maioria das pessoas acha que o teste é fácil e você pode adaptá-lo facilmente ao código existente. Ambas as suposições estão erradas. Se você embarcar em um projeto para realizar testes de unidade em seus projetos com esses dois fatos em mente, é mais provável que tenha sucesso.
fonte
Caso contrário, as iniciativas de teste automatizadas provavelmente falharão. O teste automatizado é uma habilidade, como muitas outras habilidades em programação, e se você não tem ninguém com experiência em fazer isso, não é fácil saber se um teste automatizado é um bom teste automatizado com valor real ou ruim que será falha aleatoriamente / requer atualizações frequentes / não exerce nenhum código interessante.
Se ninguém escuta, não importa se eles dizem que o teste não é bom. (Observe que o poder de liderança não precisa ser formalizado. Ter uma equipe que se importa também é bom.)
Os desenvolvedores são preguiçosos. Você precisa tornar as coisas que você deseja que sejam fáceis de realizar e as coisas que você não quer que sejam mais difíceis de realizar. Você deve certificar-se de que as bibliotecas de teste facilitem as tarefas associadas à configuração e desmontagem de testes, especialmente a configuração relacionada ao ambiente, como bancos de dados de teste ou similares. (A zombaria do banco de dados é discutida em alguns desses comentários, mas deve ser usada com cautela. Um banco de dados real deve ser fácil de rodar e permite testar a interação de componentes e ciclos de vida do processo, geralmente mais importantes e mais eficazes que o teste de unidade um acessador de dados individual.)
Você também deve garantir que seus IDEs tenham uma boa maneira de iniciar o conjunto de testes. Você deve executar o conjunto de testes com frequência para que as pessoas percebam quando ele falha, em vez de deixá-lo na miséria. Os desenvolvedores também respondem bem ao feedback, por exemplo, um sistema de integração automatizado revertendo suas alterações se eles tiverem quebrado um teste. Ou melhor, feedback positivo: um sistema de integração automatizado que captura bugs e evita que você quebre as coisas.
fonte
Primeiro, se seus desenvolvedores não vêem o valor de seus testes, provavelmente é porque seus testes não são valiosos, não porque seus desenvolvedores são cegos ao seu valor ou ao valor dos testes em geral. Entre seus evangelistas, há uma tendência de acreditar que o desenvolvimento orientado a testes não pode falhar, mas apenas por desenvolvedores preguiçosos. Eu acho que isso é errado e contraproducente.
Quando fui apresentado ao desenvolvimento orientado a testes, isso significou, efetivamente, escrever um teste para verificar se um método que nunca falha nunca falha. O que é legal, a princípio, porque você recebe um lindo cheque verde e uma sensação de realização. Mais tarde, depois de refatorar o código, você tem dezenas de Xes vermelhos irritantes, nenhum dos quais diz mais do que o código foi alterado, que os testes não são mais válidos e que você perdeu muito tempo escrevendo-os.
Você quer evitar isso.
Desde então, adotei uma abordagem diferente para os testes. Em vez de um par de implementação de interface , eu tenho uma interface, implementação, teste triplo . A interface especifica o comportamento, a implementação executa o comportamento, o teste verifica o comportamento.
Suponho que parece óbvio, mas para mim, ele distingue entre o código que você deve provar que funciona como especificado e o código que você pode testar tanto ou pouco quanto considerar apropriado. O código que você deve provar é a interface que você oferece para o exterior; o resto é sua preocupação sozinho.
Nesse caso, eu perguntaria aos desenvolvedores se eles veem uma divisão natural no código em que esse tipo de teste seria apropriado. Existe uma interface que o Time A implementa e o Time B use? Nesse caso, é do interesse da equipe B garantir que a interface se comporte conforme o esperado. Peça à Equipe B para escrever um teste e peça à Equipe A para garantir que sua implementação esteja em conformidade com o teste; ou, se não, e intencionalmente não, discutir a mudança inesperada com a outra equipe, para que eles possam se preparar.
Eu acho que isso ilustraria o valor do teste. Não é um fim em si mesmo, apesar dos adoráveis cheques verdes. Existe para explicitar a promessa feita por um desenvolvedor a outro e para garantir que a promessa seja mantida para a satisfação de ambos.
fonte
Adicionar muitos testes de unidade a um grande projeto preexistente é um trabalho árduo. Se você já encontrou uma boa estrutura de zombaria que funciona para você, deveria ter resolvido o problema mais difícil.
Sugiro tentar adicionar testes à medida que você adiciona recursos / corrige bugs. A correção de bugs é a mais fácil. Escreva um teste que falhe devido ao seu erro e corrija-o. Ao mesmo tempo, você provavelmente se encontrará escrevendo alguns testes mais simples que passam. Claro que você realmente deseja usar um pequeno e facilmente testado código para isso.
Quando as pessoas começarem a se acostumar a escrever testes para as coisas mais fáceis, esperamos que elas escrevam seu código para serem mais testáveis.
Eu também recomendaria que você medisse a cobertura de código de seus testes (eu usei cobertura para Java no passado). Você precisará de um servidor de integração contínuo executando os testes e produzindo as métricas regularmente (todos os dias, todos os check-in). Se seus colegas desenvolvedores estiverem interessados, eles verão a cobertura aumentar ao longo do tempo e poderão ver os buracos de cobertura em algumas de suas
fonte
Eu acho que você pode ter que jogar o jogo longo. Uma coisa que você pode fazer para obter alguma aceitação é tentar testar exaustivamente o próximo recurso que você escreve e acompanhar o número de bugs ao longo do tempo. Esperamos que você descubra que os principais erros serão detectados desde o início (principalmente se você associar isso ao design orientado a testes) e o número de regressões deve ser muito baixo. Após um período de tempo, digamos 1 ano, compare as estatísticas com recursos não testados em unidade de complexidade semelhante. Se você puder mostrar que o número de novos bugs e regressões é consideravelmente menor, você forneceu uma justificativa financeira para isso e fica mais difícil para a equipe de produto ignorar.
Eu tive uma situação em que pude usar o TDD e o teste de unidade para um recurso importante. Após o final da fase de desenvolvimento, não houve um único bug relatado em mais de 5 anos. Quando um aprimoramento novo e arriscado foi solicitado, eu pude implementá-lo e capturar todas as regressões nos testes de unidade.
fonte
É minha opinião forte que o valor dos testes unitários é amplamente subestimado por muitas equipes devido a vários fatores, muitos já destacados nas respostas.
Muitas vezes, os desenvolvedores estão sob pressão para "fazer as coisas", portanto, provar que um bloco de código funciona é uma prova suficiente para o cliente. Isso quase sempre se aplica à empresa de consultoria e ao controle de qualidade humano: se o cliente não precisar de testes de unidade e considerar uma demonstração ao vivo suficiente, o cliente falhará totalmente, pois assinará a aprovação do código que pode ocultar falhas.
Muitas vezes, os desenvolvedores ficam frustrados. Ser um programador é uma tarefa difícil: concluir uma tarefa e passar para a próxima é gratificante, para que todos desejem se apressar e terminar. Até serem atropelados por um ônibus com um bug grave que aumenta meses após o controle de qualidade original. Nesse cenário, o controle de qualidade automatizado e contínuo é um problema de gerenciamento e não de desenvolvedores (eles ainda serão pagos pelo trabalho, talvez horas extras).
Mas há uma exceção
Eu acredito firmemente que a aceitação do modelo de teste automatizado é uma função da "humanidade" dos testes que estão sendo feitos. Se você estiver testando um módulo da Web com um front end, é mais provável, apesar de ferramentas como o Selenium, preencher o formulário sozinho, ver o resultado e acreditar em determinismo. Você esquecerá de executar os testes mais tarde ou ficará com preguiça de fazer testes antigos novamente, e é por isso que os erros às vezes são descobertos mais tarde. Para alavancar isso, uma forte modularização do código e regras estritas sobre "modificar código antigo" foram provadas aceitáveis em um ambiente bancário (na minha experiência pessoal de trabalho).
Em vez disso, se o desenvolvedor estiver encarregado de desenvolver um módulo de dados altamente automatizado e de alto volume, ele provavelmente escreverá testes de unidade completos e os enviará para os lotes de teste. Isso porque o preenchimento de uma grande carga XML com dados convertidos de uma fonte de dados externa (zombada ou não) não é um trabalho propenso a humanos. Alguns desenvolvedores de teste eventualmente criarão um front end minúsculo e engraçado para esse tipo específico de teste. Quando trabalhei na minha tese de mestrado, estava trabalhando em um barramento de log que lidava com mais de 6000 mensagens syslog por segundo e tive que medir a perda e a corrupção de pacotes: naturalmente escrevi testes de unidade e estresse para quase todos os componentes, especialmente o analisador Syslog.
Para tornar os desenvolvedores mais propensos a testes de unidade
Eu acredito que eles devem ser forçados a. Se você é um cliente inteligente, precisará de seus consultores para executar o conjunto completo de testes em cada controle de qualidade. Se você é um bom líder de equipe, pense em atribuir a seguinte tarefa a um desenvolvedor inteligente: crie uma plataforma de teste interno. Isso não tem nada a ver com o antipatter da plataforma de efeito interno, mas, em vez disso, é um conjunto de classes auxiliares, simulações de bancos de dados, configurações, analisadores, conversores, canivetes suíços para ajudar os desenvolvedores a criar testes em pouco tempo.
As plataformas de teste atuais, como o NUnit, são de uso geral e permitem verificar asserções genéricas. O uso correto de injeção de dependência e fábricas específicas do projeto ajuda os desenvolvedores a escrever menos código para testes e a serem mais felizes. Ainda não tive a chance de experimentar isso em um projeto completo, não posso fornecer feedback da vida real.
fonte
O teste automatizado é como o desenvolvimento de software. Infelizmente, as pessoas que você contrata para testes destinam-se originalmente a escrever casos de teste, planos, estratégia, acompanhar o processo de revisão, testar manualmente e registrar bugs.
Assim que recebem responsabilidades de teste automatizadas, isso inclui uma certa quantidade de desenvolvimento de software. O problema aqui é que os testes automatizados, independentemente de quais ferramentas você usa (e, pelo amor de Deus, não discutem esse ponto), precisam de manutenção e atualização diariamente. À medida que os desenvolvedores alteram o código,
non-functional
testes separados e não espere que eles executem diariamente, leva tempo para mantê-los atualizados e bons. Mas não desista, verifique se eles são mantidos.Você falhou devido a esses motivos
if
e umwhile
loop. Como francamente nenhum curso ensina testes automatizados, eles apenas ensinam testes manuais.Isso é da minha experiência trabalhando para empresas que levam muito a sério os testes automatizados e entendem que o desenvolvedor é importante como engenheiros de testes automatizados. E pela minha experiência trabalhando para pessoas que não sabem, entenda a diferença, não importa o quanto você as explique.
fonte