---
title: "Testes de software em Continuous Delivery: além dos testes unitários e de integração"
date: 2025-03-16
reading_time: 7 min
---

Testes de software em Continuous Delivery: além dos testes unitários e de integração

testes de software em continuous delivery

Muitos desenvolvedores ainda estão presos ao passado, a práticas obsoletas de testes, de épocas em que os projetos se focavam em lançamentos de longo prazo. Naqueles tempos, dependíamos de profissionais de Quality Assurance (QA) para a execução de testes manuais, ou de Test Automation Engineers (TAE) para a construção de testes automatizados.

Hoje em dia, todas as empresas que trabalham com tecnologia aspiram a implementar Continuous Delivery (Entrega Contínua), mas nem todas estão realmente preparadas para alcançar esse objetivo. A busca pelo Continuous Delivery levou a uma diminuição na presença de profissionais de QA nas organizações. Os profissionais de TAE também enfrentaram desafios, tornando-se um gargalo para essa prática de Engenharia de Software, já que o ritmo de desenvolvimento geralmente supera a capacidade de automação de testes desses profissionais.

Para implementar com sucesso o Continuous Delivery, é fundamental automatizar a maior quantidade possível de testes, reduzindo a dependência dos testes manuais. Para isso, é crucial envolver todos os Engenheiros de Software na construção de todos os tipos de testes, não apenas os unitários e de integração. Isso visa equilibrar a relação entre a velocidade de entrega e a qualidade do software.

Quando priorizamos o Continuous Delivery sem implementar todos os testes necessários, comprometemos a qualidade do software e a continuidade operacional, o que pode gerar novos problemas no sistema, de forma semelhante ao que ocorria quando as equipes não tinham profissionais de QA.

Se as organizações desejam prescindir dos profissionais de Quality Assurance (QA), devem garantir que seu software tenha uma cobertura adequada de testes automatizados. Caso contrário, estaríamos retrocedendo em vez de avançar.

Benefícios dos testes de software

Os testes de software permitem que as organizações economizem tempo e dinheiro, garantindo a estabilidade e manutenibilidade do software, assegurando que as funcionalidades operem conforme o previsto e reduzindo os erros em produção. Isso, por sua vez, diminui os custos de desenvolvimento e suporte.

O tempo de desenvolvimento de novas funcionalidades é reduzido ao contar com um conjunto de testes que assegura que a nova funcionalidade esteja completa e pronta para entrega. Isso permite que os desenvolvedores façam estimativas de prazos mais precisas e reduz a probabilidade de bugs. Além disso, reduzem-se os custos gerais de manutenção e assegura-se que as funcionalidades já entregues continuem funcionando corretamente.

Níveis de testes de software

Existem diversos níveis de testes de software, e cada um complementa os outros. Poderia me estender aqui sobre os padrões de testes, a pirâmide de testes ou a pirâmide invertida (ice cream cone testing), mas no final, tudo se resume à estratégia que uma equipe ou organização adota para priorizar os testes. Na minha opinião, independentemente da estratégia, é essencial realizá-los. Portanto, deixo que cada organização decida o que é melhor para seu contexto e seus acordos.

Vamos aos tipos de testes:

Unit testing (Testes unitários)

Os testes unitários são fundamentais no desenvolvimento de software, pois determinam a cobertura de código e devem ser os únicos a fazê-lo. É comum que desenvolvedores incluam outros tipos de testes na cobertura, mas isso distorce a medição real.

Nos testes unitários, verificam-se as entradas e saídas de unidades de código individuais. Testam-se classes ou módulos de forma completamente independente, verificando cada linha de código e as possíveis variações. É fundamental incluir as exceções e os cenários de erro nos testes.

Os componentes da interface do usuário (frontend) também devem ser considerados, não apenas o backend. Os testes unitários são executados utilizando mocks, simulando todas as integrações necessárias para isolar a unidade de código. Isso garante que apenas a unidade em questão esteja sendo testada, o que torna os testes mais rápidos e eficientes.

Uma boa prática para melhorar a eficiência desse tipo de teste é seguir os princípios SOLID.

Integration testing (Testes de integração)

Os testes de integração verificam a interação entre dois ou mais módulos dentro do sistema, utilizando mocks para simular dados e comunicações externas.

Pessoalmente, considero esses testes os menos atraentes e, em alguns casos, podem ser redundantes dependendo do conjunto de testes implementado. Testes funcionais bem projetados podem facilmente cobrir os casos de teste de integração. Os testes de integração se tornam necessários quando um cenário específico não contemplado nos testes funcionais precisa ser testado, ou quando módulos são compartilhados com aplicações externas.

Functional testing (Testes funcionais)

Os testes funcionais simulam a experiência completa do usuário e podem facilmente ser confundidos com os testes end-to-end devido à sua semelhança. A principal diferença é que os testes funcionais são executados localmente utilizando mocks, enquanto os testes end-to-end são realizados em um ambiente real com dados reais.

Nos testes funcionais, verifica-se o correto funcionamento de todas as funcionalidades, casos de uso, validações, alertas, exceções e qualquer outro aspecto relevante para a aplicação.

Exemplos:

  • Frontend: Sequência de passos (cliques e preenchimento de campos) para executar a ação requerida e verificar uma funcionalidade na interface do usuário (UI).
  • REST API: Testes dos diferentes endpoints com seus dados de entrada e respostas, validando tanto os dados quanto as exceções.
  • Worker: Execução de um job ou processo, verificando seus dados de entrada e as respostas ou mudanças geradas.
  • Backend MVC: Semelhante aos testes de REST API, mas também se verifica o renderizado das views de acordo com a ação executada.

É fundamental contar com casos de uso e testes definidos pela equipe de produto para garantir o correto funcionamento da aplicação e estabelecer um conjunto mínimo de testes necessários.

End-to-end testing (Testes de ponta a ponta)

Os testes end-to-end são semelhantes aos testes funcionais, mas são executados em um ambiente real com dados reais, geralmente em um ambiente de staging. Também é possível executá-los em produção com um conjunto de testes controlado.

Esses testes são fundamentais para verificar que todos os componentes necessários para executar uma funcionalidade estejam corretamente configurados. Por exemplo, podem detectar a omissão de configurar um secret ou uma variável de ambiente em produção, o que poderia gerar problemas para os usuários.

Exploratory testing (Testes exploratórios de software)

Esses testes consistem em atribuir tarefas a usuários para que testem a aplicação, procurando bugs, falhas de segurança, comportamentos inesperados ou casos de uso não contemplados. Algumas organizações até oferecem recompensas aos usuários que identifiquem problemas.

São testes comuns na área de User Experience (UX). É um teste que fomenta a aprendizagem contínua por parte do testador, é altamente adaptável e pode ser utilizado para testar qualquer tipo de software. Os testes exploratórios frequentemente se concentram na experiência do usuário, o que permite descobrir problemas de usabilidade que poderiam não ser evidentes nos testes.

Outros testes

Coverage (Cobertura)

Geralmente, executa-se uma análise com Sonarqube (ou outra ferramenta semelhante) para obter o resultado da cobertura de código. Se esse resultado for igual ou superior ao limiar estabelecido pela equipe ou organização, o teste é considerado aprovado. Algumas organizações configuram esse teste como um requisito bloqueante para o deploy.

Contract testing (Testes de contrato)

Esses testes têm como objetivo garantir a consistência das entradas e respostas de uma API ao longo do ciclo de vida de um endpoint, prevenindo assim problemas com integrações futuras ou existentes.

Verificam-se os tipos de dados e seus formatos para evitar inconsistências.

API Lint

Esses testes garantem que nossa API cumpra com os padrões REST ou outras regras necessárias. Isso permite que os desenvolvedores trabalhem sob um padrão comum, evitando problemas futuros na integração de endpoints e facilitando a compreensão e o uso da API.

Performance (Desempenho)

São testes que nos ajudam a avaliar como um sistema ou aplicação se comporta sob uma carga de trabalho específica. Seu principal uso é identificar e resolver problemas de desempenho antes que o software seja lançado ao público ou quando temos mudanças consideráveis.

Nos ajudam a garantir a satisfação do usuário, a planejar a escalabilidade do sistema, prevenir falhas em produção e a otimização correta dos recursos.

Profiling POD testing

Esses testes são semelhantes aos testes de desempenho, mas seu objetivo principal é medir a capacidade de recursos que um POD necessitará para atender a uma demanda específica. Nos ajudam a definir com precisão a quantidade de CPU, memória e a estratégia de escalabilidade dos nossos PODs.

Conclusão

Um sistema deveria ter, no mínimo, Unit testing e Functional testing para seu deploy em produção. Recomenda-se uma cobertura de testes unitários de 80% e que as funcionalidades críticas estejam cobertas pelos testes funcionais. No entanto, para alcançar um desenvolvimento de software bem-sucedido com Continuous Delivery, é necessário maximizar a quantidade de testes possíveis, garantindo assim a qualidade e a continuidade operacional do sistema.

Todos os tipos de testes devem ser executados em todos os serviços de um sistema, não apenas no frontend. Isso implica que os testes funcionais e end-to-end devem ser aplicados também a APIs, Workers e qualquer componente do backend. Cada parte do sistema deve ser testada para garantir a qualidade do software e a continuidade operacional, aproveitando a rapidez com que os deploys são gerados através do Continuous Delivery.

Referências: