Um tema recorrente que me deparei na minha carreira é ser o novo desenvolvedor a entrar em uma equipe e ter rapidamente uma desconfiança inerente à unidade existente e aos conjuntos de testes de integração.
Durante a entrevista, a gerência lhe diz que eles "apóiam fortemente o teste de unidade" e que o encorajam abertamente. Eles fazem, mas tudo sobre os testes em si é simplesmente errado. Como o fato de estarem reivindicando 100% de cobertura quando houver 100% de cobertura de teste de integração, mas menos de 10% de cobertura de teste de unidade repetível. Alguns outros problemas que encontrei:
Nenhuma indicação clara entre o que é um teste de unidade e o que é um teste de integração. Os testes de unidade e integração são combinados na mesma classe.
Testes de integração que possuem dependências explícitas não declaradas de dados dinâmicos muito específicos no banco de dados de um ambiente específico.
Testes de integração não transacional, basicamente testes que podem ou não se preocupar em limpar depois de si mesmos, às vezes exigindo "limpeza" manual do banco de dados para tornar o teste repetitivo.
Nenhuma zombaria, e o código do aplicativo requer uma grande revisão apenas para que a zombaria seja possível. Em outras palavras, projete sem testar.
Não há convenções de nomenclatura claras para examinar rapidamente o nome de um teste e determinar aproximadamente quais testes estão sendo feitos.
Isso não quer dizer que TODOS os testes são inúteis ou ruins, muitos deles são muito bons e merecem ser mantidos, mas às vezes parece garimpar ouro. Eu evitava propositalmente executar testes apenas porque tinha medo de danificar o banco de dados para meus casos de teste de caixa preta.
Isso essencialmente me deu uma desconfiança inerente aos testes de unidade e integração que não escrevi ou revi pessoalmente de alguma forma. Em algum nível, se você não acredita na qualidade do seu conjunto de testes, isso realmente não agrega valor à equipe ou ao projeto.
O que você faz quando se encontra nessa situação? O que você acha que o melhor plano de ataque seria enfrentar algo assim?
Todos os testes devem ser refatorados em um esforço monumental que abrange versões? Você deveria simplesmente abandonar a ideia de que este projeto herdado possa ter um dia de cobertura sólida de teste de unidade?
fonte
Respostas:
Antes de tudo, como outros pôsteres já escreveram, você deve estar satisfeito com o teste de unidade / integração (não de uma maneira técnica, quero dizer que a razão pela qual isso deve ser feito é compreendida) e incentivada pela gerência.
Antes de começar a fazer tudo, você deve expor os problemas ao gerenciamento, por que algo deve ser feito e muito diplomaticamente, para que eles não pensem que você é o melhor programador do mundo (mesmo que seja! :-). Talvez eles lhe digam que o aplicativo será substituído por algo completamente novo e, se sim, por que se preocupar? E talvez eles percebam que seria bom e acelerariam a fase de testes antes de cada versão. E seja diplomático com seus colegas de equipe , pode haver milhões de razões pelas quais é como é e simplesmente não há razão para procurar um culpado.
Uma idéia melhor seria tentar conversar com eles para que eles possam participar do esforço, e você terá menos chances de aparecer como um espertinho; seria mais "nós" do que "eu".
Agora, coloque prioridades no que você quer fazer. Priorize as tarefas, sempre sabendo que sua primeira prioridade sempre será sua atribuição atual do projeto ... Quanto ao seu problema de teste, eis o que eu faria em três fases:
Como fazer a diferença entre testes de unidade e integração? As seguintes soluções podem ser aplicadas e não são exclusivas:
Para cada teste de integração, liste qual é o "conjunto de dados" que se espera estar no banco de dados no início de cada teste e o que deve ser removido no final dele (ex: tabela X, precisa de um registro com "id" definido como "1" e "nome" definido como "foo" etc.). Observe que o que você remove pode ser maior / menor do que o que você possui no início, já que o próprio código pode adicionar / remover objetos da camada de persistência, respectivamente. Você provavelmente notará rapidamente que vários desses casos de teste precisam do mesmo conjunto de dados ou parte do mesmo conjunto de dados.
As duas primeiras fases podem ser realizadas de forma relativamente rápida ... em comparação com as demais. Agora que você possui seu conjunto de dados, use os acessórios de criação de conjunto de dados para cada caso de teste que precisar. Mas isso vai custar algum tempo ... Então você pode fazer um, ver quanto tempo custa e estimar quanto mais tempo você precisa para fazer tudo. Além disso, você pode usar esse teste para demonstrar aos colegas o que você fez e por que a vida é muito mais fácil quando você não precisa ter um banco de dados em um estado específico para realizar testes.
Você pode observar que as fases 1, 2 e 3 podem ser realizadas em uma única classe de teste, se você quiser mostrar rapidamente aos colegas / gerência como isso pode ser feito. Isso também seria útil, como Péter Török escreveu, para mostrar imediatamente o "bom caminho" para seus colegas de equipe, para que parem de produzir códigos ruins. No entanto, acho que o restante da fase 2, identificando todo o conjunto de dados de teste, é melhor realizado em um grande passo.
Quanto à API / tecnologia por trás de tudo isso, você parece conhecer o assunto.
Espero que tenha ajudado um pouco.
Nota: para minha proposta, suponho que você codifique em Java / C #, onde sei que anotações e AOP são possíveis. Tenho certeza de que isso também é possível em outros idiomas, mas não vou escrever sobre algo que não sei.
fonte
Você não poderá consertar todos os testes juntos. Eu acho que você deve se concentrar na palavra melhoria versus revisão . Nem a gerência, nem os desenvolvedores concordarão em uma revisão geral, mas se você mostrar que há uma maneira de melhorar as coisas sem afetar o projeto negativamente, é mais provável que eles ouçam.
Primeiro, você não pode 'consertar' ou refatorar o código existente, a menos que tenha uma cobertura de teste de qualidade, portanto, eu me concentraria em corrigir sua infraestrutura de teste primeiro.
Faça uma lista das coisas que precisam ser aprimoradas e tente priorizá-las. Eu acho que a capacidade de executar testes de forma independente e individual (para que eles não se afetem) e a separação dos testes de unidade e integração são algumas das primeiras coisas a se trabalhar. Você precisa facilitar para que você e outras pessoas façam a coisa certa.
No que diz respeito ao código do aplicativo ... Você não poderá fazer a revisão completa da arquitetura do aplicativo apenas para que ele possa ser testado melhor por unidade. Em vez disso, quando você inserir um novo código, tente aplicar princípios que facilitem o teste de unidade (como injeção de dependência). Você pode pensar que isso não é grande o suficiente para uma mudança, mas é incrível a rapidez com que os desenvolvedores pegam se vêem o benefício. Só precisa haver alguém que comece a fazer uma mudança para melhor.
Converse com sua equipe e faça com que eles comprem. Uma das coisas mais importantes que você pode fazer é seguir a ' Regra dos escoteiros ' e fazer pequenas melhorias para deixar uma aula ou teste em uma forma melhor do que a encontrada . Se toda a equipe aplicar essa regra, as coisas melhoram muito mais rapidamente.
Depois de um tempo, você terá muito código que segue bons princípios e áreas do aplicativo que estão em mau estado. Nesse ponto, você tem uma linha de base do que é bom e a equipe pode decidir se é benéfico fazer um refator maior para as coisas mais antigas do legado ou se pode apenas continuar como está.
fonte
Devo admitir que consideraria um presente raro chegar a um projeto em que eles já tenham um número significativo de testes de unidade / integração - nunca tive essa sorte na minha vida até agora. Mesmo que nem todos estejam funcionando como deveriam, já há um grande esforço, e mesmo que a equipe e a gerência nem sempre sigam as melhores práticas, ainda assim elas estão comprometidas com a causa, então você não precisa gastar seu tempo discutindo sobre por que vale a pena escrever testes de unidade.
No entanto, os testes que você os descreve podem realmente levar a alguma melhoria. Mas você precisa ter cuidado com seu tom ao discutir os problemas com seus colegas de equipe . Se você começar dizendo "tudo nos testes está errado" , você poderá acabar alienando o resto da equipe rapidamente. Em vez disso, você deve se concentrar em como melhorar o estado atual das coisas, que - devo repetir - ainda é significativamente melhor que a média, de acordo com a minha experiência até agora.
OMI, seu primeiro objetivo deve ser impedir a equipe de produzir mais testes ruins . Portanto, comece demonstrando o benefício de cada melhoria específica para seus colegas de equipe. Se eles virem a utilidade de uma determinada técnica - seja cortando dependências externas, restaurando o estado original após cada teste ou separando testes de unidade e integração - eles começarão a aplicá-los. Isso por si só melhorará lenta mas seguramente a qualidade geral da base de testes a longo prazo (se você tiver 1000 casos de teste ruins agora e a equipe produzir 1000 bons testes até o próximo ano, você reduzirá a proporção de testes ruins de 100% a 50%). Uma vez protegido, você pode decidir refatorar os testes existentes caso a caso. Novamente, pequenas melhorias adicionarão grandes mudanças ao longo do tempo.
Como observação, pelo tom do seu post, acho que você também pode estar em um lugar em que eu costumava estar: não confiando no trabalho de outras pessoas, incapaz de delegar tarefas a qualquer pessoa com medo de que seu trabalho não seja da sua conta. próprios padrões de qualidade. Na minha experiência, este não é um bom lugar para se estar, porque, a longo prazo, pode facilmente levar a conflitos pessoais e esgotamento. Você não pode fazer tudo sozinho, deve trabalhar em conjunto com o resto da equipe. Você só pode ter sucesso juntos.
fonte
Trabalhe para testar a independência. Se o teste X modificar o banco de dados de teste de forma que o teste Y falhe, altere o teste Y. Nesse pequeno cenário, o ponto a ser focado não é que X tenha atrapalhado o banco de dados, mas que Y tenha dependências inadequadas. Remova essas dependências (removendo o banco de dados, reestruturando o teste ou inicializando o banco de dados para um estado em que Y passará) e agora você tem mais um teste de trabalho independente. Isso é progresso (sem dúvida, "consertar" o X para não atrapalhar o banco de dados não seria).
Seja paciente e respeitoso, da melhor maneira possível, com as pessoas com quem trabalha, apesar da bagunça que elas criaram. Eles estão tentando fazer a coisa certa, com toda a probabilidade; mantenha isso em mente e ajude-os a fazer isso.
fonte
O bom de ser novo para a equipe é que você tem uma abordagem "nova" das coisas. A parte ruim pode ser que outras pessoas tenham dificuldade em acreditar em você.
Não faça uma lista de coisas a serem feitas. Mas escolha UMA coisa que pareça urgente e que outras pessoas provavelmente responderão e sugira uma solução. Se funcionar, ótimo, sugira outra solução para outro problema, com base no seu primeiro sucesso.
Mas vá devagar, um por um, e torça para que suas idéias "entendam" lentamente no novo grupo.
fonte
defina o exemplo que você deseja ver, mas aprecie a perspectiva de outro desenvolvedor em um teste: um desenvolvedor pode testar os sucessos, enquanto outro pode testar falhas, um desenvolvedor escreveu a classe e outro pode ter usado a primeira vez ao escrever o teste.
os testes existentes (erm, a maioria) ainda têm um objetivo, embora possa não ser imediatamente evidente. não recomendo revisar e refatorar tudo de uma só vez (é tedioso e propenso a erros). testes ruins precisam, em última análise, ser atualizados, reescritos ou podem simplesmente se tornar obsoletos à medida que o software evolui.
se sua abordagem aos testes for superior em alguns aspectos, as pessoas aprenderão com esse modelo ou solicitarão sua ajuda. haverá um equilíbrio de recursos, mas você pode estender conforme necessário para dar suporte aos seus testes.
em última análise, você deseja aumentar a qualidade dos programas por meio de testes e melhorar a cobertura. você pode fazer isso colocando mais ênfase nos testes e dando um bom exemplo - mas aprecie as perspectivas de outras pessoas.
ao enfatizar a importância, você pode diferenciar o ambiente operacional de seus testes - um exemplo óbvio é executar testes em paralelo; se não for reentrante, você localizou um erro em seu programa ou teste (vitória / vitória). um ambiente de teste mais rigoroso forçará os testes ruins a serem corrigidos e / ou reescritos (espero que da maneira certa na segunda vez). introduza lentamente essas alterações (não interrompa metade dos testes de uma só vez - isso é um problema real), forçando-os a aprender o que faz um bom teste e, finalmente, um bom programa. então, quando você e outros participantes modificarem / repararem / estenderem os testes, aplique o que aprendeu - é incremental e você tem uma melhor compreensão do contexto / programa da época.
fonte
Corrija-os com o tempo
Eu estive na mesma situação. Passei uma hora todas as manhãs passando por testes e corrigindo-os até que todos estivessem consertados. Era uma base de código de tamanho médio e acho que terminei em 1,5 meses. Eu também fiquei muito mais confiante em nossos testes.
Pessoalmente, não me importo se um teste é um teste de unidade ou de integração, desde que seja um bom teste. Por bom teste, quero dizer que:
Ao longo do caminho, evangelizei melhor a construção de testes (ou seja, incomodei muito as pessoas).
fonte