Descubra como combinar diferentes tipos de teste em uma estratégia razoável que corresponda ao seu projeto.
Que bom que você voltou! O último artigo apresentou muitas informações sobre como abordar os diferentes tipos de teste e o que eles contêm, além de esclarecer as definições de cada um deles. Lembra desta imagem de meme? Você pode ter se perguntado como todos os tipos de testes que você aprendeu podem funcionar juntos.
A seguir, você vai aprender exatamente isso. Neste artigo, explicamos 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 as estratégias e entender o significado dos nomes delas.
Determine as metas do teste: o que você quer alcançar com esses testes?
Antes de começar a criar uma boa estratégia, descubra qual é seu objetivo de teste. Quando você considera que seu aplicativo foi testado o suficiente?
Alcançar uma alta cobertura de teste é frequentemente visto como a meta final dos desenvolvedores. Mas será que essa é sempre a melhor abordagem? Pode haver outro fator crucial a ser considerado ao decidir sobre uma estratégia de teste: atender às necessidades dos usuários.
Como desenvolvedor, você também usa muitos outros aplicativos e dispositivos. Nesse sentido, você é o usuário que depende de todos esses sistemas para “apenas funcionar”. Por sua vez, você depende de inúmeros desenvolvedores para fazer o possível para que os aplicativos e dispositivos funcionem. Como desenvolvedor, você também se esforça para corresponder a essa confiança. Portanto, sua primeira meta deve ser sempre enviar um software que funcione e atender aos usuários. Isso se estende aos testes que você cria para garantir a qualidade do aplicativo. Kent C. Dodds resume isso muito bem na postagem Static vs Unit vs Integration vs E2E Testing for Frontend Apps (em inglês):
Quanto mais seus testes se assemelharem ao uso do software, mais confiança eles vão oferecer.
por Kent C. Dodds
Kent descreve isso como ganhar confiança nos testes. Quanto mais você se aproximar dos usuários ao escolher um tipo de teste adequado, mais poderá confiar nos resultados dos testes. Em outras palavras, quanto mais alto você subir na pirâmide, mais confiante vai ficar. Mas o que é a pirâmide?
Como determinar estratégias de teste
Como primeira etapa, determine quais partes dos requisitos você precisa verificar para garantir que elas sejam atendidas. Descubra quais tipos de teste usar e em qual nível de detalhe você pode alcançar a maior confiança, mantendo uma estrutura de custo eficiente. Muitos desenvolvedores abordam esse tópico usando analogias. Confira as mais comuns, começando pelo clássico.
O clássico: a pirâmide de testes
Assim que você começar a procurar estratégias de teste, provavelmente vai encontrar a pirâmide de automação de testes como a primeira analogia. Mike Cohn apresentou esse conceito no livro "Succeeding with Agile" (Sucesso com o Agile). Mais tarde, Martin Fowler expandiu o conceito no artigo Pirámide de testes prática. É possível representar a pirâmide visualmente da seguinte maneira:
Como mostrado nesta imagem, a pirâmide de testes consiste em três camadas:
Unidade. Esses testes estão na camada de 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 mais importantes. Por exemplo, confira 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 mais do que os testes de unidade. Um exemplo de teste de integração é um teste de API. Também é possível classificar os testes de componentes como esse tipo.
Testes E2E (também chamados de testes de interface). Esses testes simulam um usuário real 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 mencionado brevemente antes, a ordem das camadas não é uma coincidência. Eles mostram as prioridades e os custos correspondentes. Isso mostra claramente quantos testes você precisa criar 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 dão mais confiança de que o 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 competição 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 de usuário mais importantes ou os lugares mais vulneráveis a defeitos. Como Martin Fowler enfatiza, os dois pontos mais importantes da pirâmide de Cohn são os seguintes:
- Escreva testes com granularidade diferente.
- Quanto mais alto o nível, menos testes você terá.
A pirâmide evoluiu! Adaptações das pirâmides de testes
Por vários anos, as discussões giraram 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 reais. Portanto, pode ser enganoso. A pirâmide perdeu a forma? Guillermo Rauch tem uma opinião sobre isso:
Crie testes. Mas não muito. Principalmente integração.
por Guillermo Rauch
Essa é uma das citações mais citadas sobre o assunto, então vamos analisar:
- "Escrever testes". Não apenas porque gera confiança, mas também porque economiza tempo na manutenção.
- "Não muitas". A cobertura de 100% nem sempre é boa, porque os testes não são priorizados e há muita manutenção.
- "A maioria das integrações". Novamente, a ênfase é nos testes de integração: eles têm o maior valor comercial, oferecendo 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 testes e mudar seu foco para o teste de integração. Nos últimos anos, muitas adaptações foram propostas. Vamos analisar as mais comuns.
Diamante de teste
A primeira adaptação remove o excesso de ênfase nos testes de unidade, como visto na pirâmide de testes. Imagine que você alcançou 100% de cobertura nos testes de unidade. No entanto, na próxima refatoração, você vai precisar atualizar muitos desses testes de unidade, e talvez queira ignorá-los. Então, elas se desgastam.
Como resultado, e com o foco maior em testes de integração, a seguinte forma pode surgir:
Uma pirâmide evolui para um diamante. Você pode ver as três camadas anteriores, mas com um tamanho diferente, e a camada de unidade foi cortada:
- Unidade. Crie testes de unidade da mesma forma que você definiu antes. No entanto, como eles tendem a se desgastar, priorize e cubra apenas os casos mais críticos.
- Integração. Os testes de integração que você conhece, testando a combinação de unidades únicas.
- E2E. Essa camada processa os testes de interface semelhantes à pirâmide de testes. Só escreva testes E2E para os casos de teste mais críticos.
Como testar a colmeia
Há outra adaptação, introduzida pelo Spotify, que é semelhante ao diamante de teste, mas mais especializada para sistemas de software baseados em microsserviços. A grade de teste é outra analogia visual para a granularidade, o escopo e o número de testes a serem criados para um sistema de software baseado em microsserviços. Devido ao tamanho pequeno, a complexidade mais considerável em um microsserviço não está no próprio serviço, mas na forma como ele interage com outros. Portanto, uma estratégia de teste para um microsserviço deve se concentrar principalmente em testes de integração.
Essa forma 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 correção de outro sistema". Esses testes têm dependências externas que você precisa considerar. Por outro lado, seu sistema pode ser uma dependência que quebra outros sistemas. Assim como nos testes E2E em outras analogias, use esses testes com cuidado, apenas para os casos mais essenciais.
- Testes de integração. Assim como em outras adaptações, você deve se concentrar nessa camada. Ele contém testes que verificam a correção do serviço de maneira mais isolada, mas ainda em combinação com outros serviços. Isso significa que os testes também vão incluir alguns outros sistemas e se concentrar nos pontos de interação, por exemplo, por meio de testes de API.
- Testes sobre detalhes de implementação. Esses testes se assemelham a testes de unidade, que se concentram em partes do código que são naturalmente isoladas e, portanto, têm complexidade interna própria.
Para saber mais sobre essa estratégia de teste, consulte a postagem que compara a pirâmide de testes ao favo de mel de Martin Fowler e o artigo original do Spotify.
Troféu de testes
Já é possível notar um foco recorrente nos testes de integração. No entanto, outro tipo que você encontrou no artigo anterior não é um teste teórico, mas ainda é um aspecto importante a ser considerado em uma estratégia de teste. A análise estática está ausente na pirâmide de testes e na maioria das adaptações que você viu até agora. Há a adaptação do troféu de teste, que considera a análise estática, mantendo o foco nos testes de integração. O troféu de teste teve origem na citação anterior de Guillermo Rauch e foi desenvolvido por Kent C. Dodds:
O troféu de teste é uma analogia que mostra a granularidade dos testes de uma maneira um pouco diferente. Ele tem quatro camadas:
- Análise estática. Ele desempenha um papel vital nessa analogia e permite que você detecte erros de digitação, erros de estilo e outros bugs simplesmente executando as etapas de depuração já descritas.
- Testes de unidade. Eles garantem que sua unidade menor seja testada adequadamente, mas o troféu de teste não vai enfatizar isso na mesma medida que a pirâmide de testes.
- Integração. Esse é o foco principal, já que equilibra o custo e a maior confiança da melhor maneira, como em outras adaptações.
- Testes de interface. Eles incluem testes E2E e visuais, e estão no topo do troféu de testes, semelhante ao papel deles na pirâmide de testes.
Para saber mais sobre o troféu de teste, consulte a postagem do blog de Kent C. Dodds sobre o assunto.
Algumas abordagens mais focadas na interface
Isso é bom, mas não importa como você chama sua estratégia, seja "pirâmide", "colmeia" ou "diamante", ainda falta algo. Embora a automação de testes seja valiosa, é importante lembrar que o teste manual ainda é essencial. O teste automatizado deve aliviar as tarefas de rotina e permitir que os engenheiros de garantia de qualidade se concentrem em áreas cruciais. Em vez de substituir o teste manual, a automação deve complementá-lo. Há uma maneira de integrar o teste manual à automação para resultados ideais?
Testando casquinha de sorvete e caranguejo
Há duas adaptações da pirâmide de testes que se concentram mais nessas formas de teste com foco na interface. Ambos têm a vantagem de ter alta confiança, mas são naturalmente mais caros devido à execução mais lenta do teste.
O primeiro, o cone de sorvete de teste, é parecido com a pirâmide invertida. Sem a etapa de teste manual, também é conhecida como pizza de teste.
O picolé tem maior foco em testes manuais ou de interface e menor foco em testes de unidade. Muitas vezes, ela toma forma em projetos em que os desenvolvedores começaram a trabalhar com apenas algumas ideias sobre a estratégia de teste. O código de gelo é considerado um antipadrão e com razão. Ele é caro em termos de recursos e trabalho manual.
O carangue de teste é semelhante ao cone de sorvete de teste, mas com mais ênfase no teste E2E e visual:
Essa estratégia de teste inclui mais um aspecto: ela verifica se o aplicativo funciona e tem uma boa aparência. O carangue de teste destaca a importância do teste visual, definido no artigo anterior. Os testes de integração, divididos em testes de componentes e de API, passam para o segundo plano, e os testes de unidade têm um papel ainda mais secundário. Confira mais detalhes sobre essa estratégia de teste neste artigo sobre o teste de carangue.
Embora sejam mais caras, essas duas estratégias de teste têm seu lugar: por exemplo, em projetos menores, em que são necessários menos testes ou é preciso cobrir menos complexidade. Nesse caso, uma estratégia de teste completa com foco em testes de integração pode ser exagerada.
Embora essas duas estratégias de teste sejam mais caras, elas têm seu lugar, por exemplo, em projetos menores que exigem menos testes e não precisam cobrir muita complexidade. Nesse caso, uma estratégia de teste em grande escala focada em testes de integração pode ser desnecessariamente complexa.
Conselho prático: vamos elaborar uma estratégia.
Agora você já sabe quais são as estratégias de teste mais comuns. Você começou com a clássica pirâmide de testes e conheceu várias adaptações dela. Agora você precisa avaliar cada uma delas para seu produto e decidir qual é a melhor para seu projeto. A resposta a essa pergunta deve começar com a resposta favorita de todos: depende. Isso não diminui a precisão.
A escolha da estratégia de teste mais adequada entre as descritas e até mesmo as deixadas de fora depende do seu aplicativo. Ele precisa se encaixar na sua arquitetura, nos seus requisitos e, por último, mas não menos importante, nos seus usuários e nos requisitos deles. Tudo isso pode variar de acordo com o aplicativo. Isso é completamente normal. Lembre-se de que sua meta mais importante é atender aos usuários, não uma definição de livro didático.
Na maioria das vezes, os testes do mundo real são difíceis de separar e definir individualmente. Até mesmo Martin Fowler enfatiza o aspecto positivo de definições diferentes, como no caso de testes de unidade. Como Justin Searls afirma corretamente em seu tweet:
[…] escreva testes expressivos que estabeleçam limites claros, sejam executados de forma rápida e confiável e falhem apenas por motivos úteis.
por Justin Searls
Concentre-se nos testes que informam erros reais que os usuários podem encontrar e não se distraia do seu objetivo. Os testes devem ser projetados para beneficiar o usuário, não apenas fornecer cobertura de 100% ou debater qual porcentagem de qual tipo de teste escrever.
Concentre-se em testes que informem erros reais que os usuários podem encontrar e não se distraia do seu objetivo. Os testes devem ser projetados para beneficiar o usuário, não apenas fornecer cobertura de 100% ou gerar debates sobre qual porcentagem de um tipo específico de teste você deve escrever.