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.