Descubra como combinar diferentes tipos de testes em uma estratégia razoável que corresponda ao seu projeto.
Olá! O último artigo estabeleceu muitas bases sobre como abordar os diferentes tipos de teste e o que eles contêm, além de esclarecer as definições dos tipos de testes. Lembra desta imagem pequena de meme? Você pode ter se perguntando como todos esses tipos de teste que aprendeu podem funcionar juntos.
A seguir, você aprenderá exatamente isso. Este artigo apresenta uma introdução sobre como combinar esses tipos de teste em estratégias razoáveis e escolher uma que corresponda ao seu projeto.
Você pode comparar as estratégias com várias formas para entender melhor o significado delas. Confira uma lista de estratégias com os respectivos tamanhos e escopos de desenvolvimento.
Vamos analisar melhor as estratégias e aprender o significado por trás dos nomes.
Determine as metas do teste: o que você quer alcançar com esses testes?
Antes de começar a criar uma boa estratégia, defina sua meta de teste. Quando você considera que seu aplicativo foi suficientemente testado?
Alcançar uma alta cobertura de testes é muitas vezes visto como o objetivo final dos desenvolvedores quando se trata de testes. Mas será sempre a melhor abordagem? Pode haver outro fator crítico a ser considerado ao decidir sobre uma estratégia de teste, atender às necessidades dos seus usuários.
Como desenvolvedor, você também usa muitos outros aplicativos e dispositivos. Nesse aspecto, você é o usuário que depende de todos esses sistemas para "simplesmente trabalhar". Por sua vez, conta com inúmeros desenvolvedores para fazer o possível para que os aplicativos e dispositivos funcionem. Para resolver isso, como desenvolvedor, você também precisa se esforçar para respeitar essa confiança. Portanto, sua primeira meta deve ser sempre enviar um software que funcione e atender seus usuários. Isso se estende aos testes que você programa para garantir a qualidade do aplicativo. Kent C. Dodds resume tudo muito bem na postagem Estática vs Unidade vs Integração vs Testes E2E para apps de front-end:
Quanto mais seus testes se parecerem com a forma como seu software é usado, mais confiança eles podem dar a você.
de Kent C. Riscos
Kent descreve isso como um ganho de confiança nos testes. Quanto mais você se aproximar dos usuários escolhendo um tipo de teste adequado, mais confiará que seus testes terão resultados válidos. Em outras palavras, quanto mais alto você escala na pirâmide, mais confiante você fica. Mas espere, o que é a pirâmide?
Determinar estratégias de teste: como escolher uma estratégia de teste
Para começar, determine quais partes dos requisitos você precisa verificar para ter certeza de que eles foram atendidos. Descubra quais tipos de teste usar e com que nível de detalhamento é possível ter mais confiança, mantendo uma estrutura de custos eficiente. Muitos desenvolvedores abordam esse tópico usando analogias. Estas são as mais comuns, começando com o já conhecido.
O clássico: a pirâmide de testes
Assim que você começar a procurar estratégias de teste, provavelmente verá a pirâmide de automação de testes como a primeira analogia. Mike Cohn introduziu esse conceito no livro "Succeeding with Agile". Posteriormente, Martin Fowler expandiu esse conceito no artigo Practical Test Pyramid. Você pode representar a pirâmide visualmente da seguinte forma:
Como mostrado neste desenho, a pirâmide de teste consiste em três camadas:
Unidade. Esses testes estão na camada base da pirâmide porque são rápidos de executar e simples de manter. Eles são isolados e segmentam as unidades de teste menores. Por exemplo, veja um teste de unidade típico para um produto muito pequeno.
Integração. Esses testes estão no meio da pirâmide, porque têm uma velocidade de execução aceitável, mas aproximam você do usuário do que os testes de unidade podem. Um exemplo de teste de integração é um teste de API. Você também pode classificar testes de componente como esse tipo.
Testes E2E (também chamados de testes de interface). Esses testes simulam um usuário genuíno e a interação dele. Esses testes precisam de mais tempo para serem executados e, portanto, são mais caros. Eles estão no topo da pirâmide.
Confiança versus recursos
Como abordado antes, a ordem das camadas não é coincidência. Eles mostram as prioridades e os custos correspondentes. Isso dá uma ideia clara de quantos testes precisam ser criados para cada camada. Você já viu isso na definição dos tipos de teste.
Como os testes E2E são mais próximos dos usuários, eles oferecem a maior confiança de que seu aplicativo está funcionando conforme o esperado. No entanto, eles exigem uma pilha de aplicativos completa e um usuário simulado, portanto, também são potencialmente os mais caros. Portanto, a confiança está em concorrência direta com os recursos necessários para executar os testes.
A pirâmide tenta resolver esse problema fazendo com que você se concentre mais nos testes de unidade e priorize estritamente os casos cobertos pelos testes E2E. Por exemplo, as jornadas mais cruciais do usuário ou os lugares mais vulneráveis a defeitos. Como enfatiza Martin Fowler, os dois pontos mais essenciais na pirâmide de Cohn são os seguintes:
- Crie testes com granularidade diferente.
- Quanto mais alto for o nível, menos testes você precisará ter.
A pirâmide evoluiu! Adaptações das pirâmides de teste
Por vários anos, as discussões giram em torno da pirâmide. A pirâmide parece simplificar demais as estratégias de teste, deixa de fora muitos tipos de teste e não se encaixa mais em todos os projetos do mundo real. Portanto, pode ser enganosa. A pirâmide caiu de forma? Guillermo Rauch tem uma opinião sobre isso:
Crie testes. Mas não muito. Principalmente integração.
de Guillermo Rauch
Essa é uma das citações mais citadas sobre esse assunto, então vamos dividi-la:
- "Criar testes". Não apenas porque gera confiança, mas também porque economiza tempo de manutenção.
- "Não muitos". Ter 100% de cobertura nem sempre é bom, porque seus testes não são priorizados e há muita manutenção.
- "Principalmente integração". Mais uma vez, a ênfase está nos testes de integração: eles têm o maior valor comercial proporcionando um alto nível de confiança diário, mantendo um tempo de execução razoável.
Isso faz você pensar novamente sobre a pirâmide de teste e mudar seu foco para o teste de integração. Nos últimos anos, muitas adaptações foram propostas, então vamos analisar as mais comuns.
Diamante de teste
A primeira adaptação remove a ênfase exagerada no teste de unidade, como visto na pirâmide de teste. Imagine que você atingiu 100% de cobertura nos testes de unidade. No entanto, na próxima vez que você fizer a refatoração, vai ser necessário atualizar muitos desses testes de unidade e pode ficar tentado a ignorá-los. Por isso, eles sofrem erosão.
Como resultado, e em maior foco nos testes de integração, o seguinte formato pode surgir:
Uma pirâmide evolui para um diamante. As três camadas anteriores, mas com um tamanho diferente, e a camada de unidades foi cortada:
- Unidade. Programe testes de unidade da maneira que você os definiu antes. No entanto, como eles tendem a se desgastar, priorize e cobre apenas os casos mais críticos.
- Integração. Os testes de integração que você conhece, combinando unidades únicas.
- E2E. Essa camada lida com os testes de interface de forma semelhante à pirâmide de testes. Crie testes E2E apenas para os casos mais críticos.
Testando favo de mel
Há outra adaptação, introduzida pelo Spotify, semelhante ao diamante de teste, mas ainda mais especializada para sistemas de software baseados em microsserviços. O honeycomb é outra analogia visual com relação à granularidade, ao escopo e ao número de testes a serem criados para um sistema de software baseado em microsserviços. Devido ao seu pequeno tamanho, a maior complexidade em um microsserviço não está dentro do serviço em si, mas em como ele interage com os outros. Portanto, uma estratégia de teste para um microsserviço deve se concentrar principalmente em testes de integração.
Esse formato lembra um favo de mel, por isso o nome. Ele tem as seguintes camadas:
- Testes integrados. O artigo do Spotify usa uma citação de J. B. Rainsberger para definir essa camada: "Um teste que será aprovado ou reprovado com base na exatidão de outro sistema". Esses testes têm dependências externas que você precisa considerar e, por outro lado, seu sistema pode ser uma dependência que corrompe outros sistemas. De forma semelhante aos testes E2E em outras analogias, use esses testes com cuidado, somente para os casos mais essenciais.
- Testes de integração. Assim como em outras adaptações, é preciso se concentrar nessa camada. Ela contém testes que verificam a exatidão do serviço de forma mais isolada, mas ainda em combinação com outros serviços. Isso significa que os testes também incluirão outros sistemas e se concentrarão nos pontos de interação, por exemplo, por meio de testes de API.
- Testes nos detalhes da implementação. Esses testes se assemelham a testes de unidade, que se concentram em partes do código naturalmente isoladas e, portanto, têm complexidade interna própria.
Para saber mais sobre essa estratégia de teste, confira a postagem que compara a pirâmide de teste ao favo de mel de Martin Fowler e o artigo original do Spotify.
Troféu de teste
Já é possível notar um foco recorrente nos testes de integração. No entanto, outro tipo que você encontrou no artigo anterior não é o teste teórico, mas ainda é um aspecto importante que você deve considerar em uma estratégia de teste. A análise estática está ausente na pirâmide de teste e na maioria das adaptações que você viu até agora. Já a adaptação do troféu de teste considera a análise estática, mantendo o foco nos testes de integração. O troféu de teste originou-se da citação anterior de Guillermo Rauch e foi desenvolvido por Kent C. Riscos:
O troféu de teste é uma analogia que descreve a granularidade dos testes de uma maneira ligeiramente diferente. Ela tem quatro camadas:
- Análise estática. Ele desempenha um papel vital nessa analogia e permite que você detecte erros de digitação, de estilo e outros bugs simplesmente executando as etapas de depuração já descritas.
- Testes de unidade: Eles garantem que sua menor unidade seja testada adequadamente, mas o troféu de teste não as enfatizará na mesma medida da pirâmide de teste.
- Integração. Esse é o foco principal, porque equilibra o custo e a maior confiança da melhor maneira, como acontece com outras adaptações.
- Testes de interface. Incluindo testes visuais e de E2E, eles estão no topo do troféu de teste, semelhante à função deles na pirâmide de testes.
Para ler mais sobre o troféu de teste, consulte a postagem no blog de Kent C. Dodds sobre isso.
Algumas abordagens mais focadas na IU
Isso é muito bom, mas não importa como você chama sua estratégia de "pirâmide", "favo de mel" ou "diamante", ainda falta algo. Embora a automação de testes seja valiosa, é importante lembrar que o teste manual ainda é essencial. Os testes automatizados devem aliviar tarefas de rotina e liberar os engenheiros de garantia de qualidade para se concentrarem em áreas cruciais. Em vez de substituir o teste manual, a automação deve complementá-lo. Existe uma maneira de integrar o teste manual com a automação para ter os melhores resultados?
Teste de casquinha de gelo e de caranguejo
De fato, há duas adaptações da pirâmide de testes que se concentram mais nessas formas de teste focadas na interface. Ambos têm a vantagem de alta confiança, mas são naturalmente mais caros devido à execução mais lenta do teste.
A primeira, o cone de gelo de teste, parece com a pirâmide ao contrário. Sem a etapa de teste manual, ela também é conhecida como pizza de teste.
O cone de gelo tem mais foco em testes manuais ou de interface e menos foco no teste de unidade. Muitas vezes, isso toma forma em projetos em que os desenvolvedores começaram a trabalhar com apenas alguns pensamentos sobre a estratégia de teste. O código de gelo é considerado um antipadrão e com razão, mas é caro em termos de recursos e trabalho manual.
O caranguejo de teste é semelhante ao cone de gelo do teste, mas com mais ênfase em E2E e testes visuais:
Essa estratégia de teste tem mais um aspecto: verifica se o aplicativo funciona e se apresenta em bom estado. O caranguejo de teste destaca a importância do teste visual, definido no artigo anterior. O teste de integração, dividido em testes de componentes e de API, passa para o segundo plano, e o teste de unidade desempenha um papel ainda mais secundário aqui. Confira mais detalhes sobre essa estratégia de teste neste artigo sobre o caranguejo de teste.
Embora sejam mais caras, essas duas estratégias de teste têm seu lugar: por exemplo, em projetos menores, em que menos testes são necessários ou menos complexidade precisa ser abordada. Nesse caso, uma estratégia de teste totalmente desenvolvida com foco no teste de integração pode ser exagerada.
Embora essas duas estratégias de teste sejam mais caras, elas são úteis, por exemplo, em projetos menores que exigem menos testes e não precisam abranger muita complexidade. Nesse caso, uma estratégia de teste de escala completa com foco no teste de integração pode ser desnecessariamente complexa.
Conselho prático: vamos criar estratégias!
Agora você já conhece as estratégias de teste mais comuns. Você começou com o clássico, a pirâmide de teste, e conheceu suas muitas adaptações. Agora você precisa avaliá-los para seu produto e decidir qual é o melhor para seu projeto. A resposta a essa pergunta deve começar com a favorita de todos "Depende". No entanto, isso não torna a busca menos precisa.
A escolha da estratégia de teste mais apropriada entre as descritas (e até mesmo as deixadas de fora) depende do seu aplicativo. Ela deve se basear na sua arquitetura, nos seus requisitos e, por último, mas não menos importante, nos seus usuários e seus requisitos. Tudo isso pode variar de aplicativo para aplicativo. Isso é completamente normal. Lembre-se de que sua meta mais importante é atender aos usuários, não uma definição feita em um livro didático.
Na maioria das vezes, é difícil separar e definir testes do mundo real individualmente. Até mesmo Martin Fowler enfatiza o aspecto positivo das definições diferentes, como no caso dos testes de unidade. Como Justin Searls afirma corretamente em seu tweet:
[...] programar testes expressivos que estabeleçam limites claros, sejam executados com rapidez e confiança e falhem somente por motivos úteis.
de Justin Searls
Concentre-se nos testes que relatam erros reais que os usuários podem encontrar e não se distraem com sua meta. Os testes devem ser elaborados para beneficiar o usuário, não apenas para fornecer 100% de cobertura ou para debater qual porcentagem do tipo de teste escrever.
Concentre-se em testes que relatam erros reais que os usuários podem encontrar e que não se distraem com seu objetivo. Os testes devem ser elaborados para beneficiar o usuário, não apenas para fornecer 100% de cobertura ou gerar debates sobre qual porcentagem de um tipo de teste específico você deve programar.