Como começar a usar integração contínua

Saiba como adotar a integração contínua e testes automatizados em 5 etapas.

Sten Pittet Sten Pittet

A Integração contínua (CI) é uma prática recomendada ágil e de DevOps em que uma equipe de desenvolvedores integra o código cedo e com frequência à ramificação principal ou repositório de código. O objetivo é reduzir o risco de ver o “inferno da integração” ao esperar o final de um projeto ou um sprint para mesclar o trabalho de todos os desenvolvedores. Devido à automatização da implementação, a CI ajuda as equipes a atender aos requisitos de negócios, melhorar a qualidade do código e aumentar a segurança.

Um dos principais benefícios de adotar a IC é que ela economiza tempo durante seu ciclo de desenvolvimento, identificando e abordando conflitos com antecedência. Também é uma ótima maneira de reduzir o tempo gasto na atualização de segurança e regressão dando mais ênfase a ter um bom conjunto de testes. Por fim, ajuda a compartilhar um melhor entendimento da base de código e dos recursos que você está desenvolvendo para seus clientes.

O primeiro passo na jornada para a integração contínua: configuração de testes automatizados.

Introdução a teste automatizado

Entendendo os diferentes tipos de testes

Para obter todos os benefícios da CI, você precisará automatizar seus testes para poder executá-los para cada alteração feita ao repositório principal. Insistimos em executar testes em cada branch do seu repositório, e não apenas focar o branch principal. Dessa maneira, você poderá capturar problemas mais cedo e minimizar interrupções à equipe.

Existem muitos tipos de testes implementados, mas não é necessário fazer tudo de uma vez se você está apenas começando. Você pode começar pequeno com testes de unidade e trabalhar para estender sua cobertura ao longo do tempo.

  • Testes unitários têm um escopo restrito e no geral verificam o comportamento de métodos ou funções individuais.
  • Testes de integração garantem que vários componentes se comportem bem juntos. Isso pode envolver diversas classes, bem como teste da integração com outros serviços.
  • Testes de aceitação são semelhantes aos testes de integração, mas se concentram nos casos de negócios em vez dos próprios componentes.
  • Testes de interface do usuário garantem que o aplicativo funcione bem desde a perspectiva do usuário.

Nem todos os testes são iguais, e você pode visualizar as concessões que você fará com a pirâmide de teste desenvolvida por Mike Cohn.

Triângulo de testes

Os testes unitários são rápidos e baratos de implementar, pois de forma geral fazem verificações em pequenos trechos de código. Por outro lado, os testes de interface do usuário são complexos de implementar e lentos para executar, pois de forma geral exigem que um ambiente completo seja iniciado, bem como vários serviços para emular o navegador ou comportamentos móveis. Logo, você pode querer limitar o número de testes complexos de IU e contar com bons testes unitários na base para ter uma compilação rápida e obter feedback para os desenvolvedores o mais rápido possível.

Fazendo testes automáticos

Para adotar a integração contínua, você vai precisar executar seus testes em cada mudança que for enviada para o branch principal. Assim, você precisa ter um serviço que possa monitorar o repositório e atender novos pushes para a base de código. Existem muitas soluções que você pode escolher tanto na premissa quanto no Cloud. Você deve considerar o seguinte ao escolher seu servidor:

  • Onde seu código está hospedado? O serviço de CI pode acessar sua base de código? Você tem uma restrição especial sobre onde o código pode residir?
  • De que SO e recursos você precisa para o aplicativo? Seu ambiente de aplicativos tem suporte? Você pode instalar as dependências certas para compilar e testar seu software?
  • De quantos recursos você precisa para os testes? Alguns aplicativos de Cloud podem ter restrições em relação os recursos que você pode usar. Se o software consome muitos recursos, talvez você queira hospedar o servidor de CI atrás do firewall.
  • Quantos desenvolvedores há em sua equipe? Quando sua equipe praticar CI, você vai ter muitas alterações enviadas para o repositório principal todos os dias. Para que os desenvolvedores obtenham um feedback rápido, você precisa reduzir o tempo de fila para os builds e usar um serviço ou servidor que ofereça a simultaneidade adequada.

No passado, você normalmente precisava instalar um servidor de CI separado, como Bamboo ou Jenkins, mas agora você pode encontrar soluções na nuvem que são muito mais simples de adotar. Por exemplo, se o seu código estiver hospedado no Bitbucket Cloud, você poderá usar o recurso de pipelines no seu repositório para executar testes em cada push sem necessidade de configurar agentes de build nem um servidor separado e sem restrição à concomitância.

image: node:4.6.0 pipelines:   default:     - step:         script:           - npm install           - npm test

Exemplo de configuração para testar o repositório Javascript com o Bitbucket Pipelines.

Use cobertura de código para localizar código não testado

Depois de adotar o teste automatizado, é uma boa ideia combiná-lo com uma ferramenta de cobertura de teste que lhe dará uma ideia de quanto de sua base de código é coberto pelo seu conjunto de testes.

É bom ter como objetivo uma cobertura de mais de 80%, mas tenha cuidado para não confundir um alto percentual de cobertura com um bom pacote de teste. Uma ferramenta de cobertura de código ajudará você a encontrar código não testado, mas é a qualidade dos testes que fará a diferença no final.

Se você está apenas começando, não se apresse em atingir 100% de cobertura de sua base de código, mas, sim, use uma ferramenta de cobertura de teste para descobrir as partes críticas de seu aplicativo, que ainda não têm testes e comece por aí.

Refatoramento é uma oportunidade para adicionar testes

Se você está prestes a fazer alterações significativas em seu aplicativo, deve começar escrevendo testes de aceitação em torno dos recursos que podem ser afetados. Eles servem como uma rede de segurança para garantir que o comportamento original não tenha sido afetado depois que você refatorou o código ou adicionou novos recursos.

Adotando integração contínua

Embora automatizar seus testes seja uma parte fundamental da CI, por si só não é suficiente. Você pode precisar mudar a cultura de sua equipe para garantir que os desenvolvedores não trabalhem dias em um recurso sem mesclar suas alterações de volta ao branch principal, e você vai precisar aplicar uma cultura de construção verde

Integrar desde o princípio e com frequência

Esteja você usando desenvolvimento central ou branches de recursos, é importante que os desenvolvedores integrem suas alterações o mais rápido possível no repositório principal. Deixando o código ficar em um branch ou na estação de trabalho do desenvolvedor por muito tempo, você se expõe ao risco de ter muitos conflitos para examinar quando decidir fazer o merge das coisas de volta ao branch principal.

Com a integração antecipada, você reduz o escopo das mudanças, o que torna mais fácil entender os conflitos quando você os tem. A outra vantagem é tornar mais fácil o compartilhamento de conhecimento entre os desenvolvedores, pois eles vão obter mudanças mais digeríveis.

Se você estiver fazendo algumas alterações que podem impactar um recurso existente, você pode usar marcadores de recurso para desligar suas alterações na produção até que seu trabalho seja concluído.

Mantenha o build verde sempre

Se um desenvolvedor interrompe o build do branch principal, consertá-lo se torna a principal prioridade. Quanto mais mudanças entrarem no build enquanto ele estiver quebrado, mais difícil vai ser para você entender o que o quebrou - e você também corre o risco de introduzir mais falhas.

Vale a pena gastar tempo em seu conjunto de testes para ter certeza de que ele pode falhar rapidamente e dar feedback ao desenvolvedor que implementou as alterações o mais rápido possível. Você pode dividir seus testes para que os mais rápidos (testes de unidade, por exemplo) sejam executados antes dos testes de longa duração. Se o seu conjunto de testes sempre leva muito tempo para falhar, você vai perder muito tempo do desenvolvedor, pois eles vão ter que mudar o contexto para voltar ao trabalho anterior e corrigi-lo.

Não se esqueça de definir notificações para garantir que os desenvolvedores sejam alertados quando o build for interrompido. Você também pode dar um passo adiante exibindo o estado dos branches principais em um painel em que todos podem vê-lo.

Escreva testes como parte de suas histórias

Por último, você vai precisar se certificar de que cada recurso desenvolvido tenha testes automatizados. Pode parecer que você vai abrandar o desenvolvimento, mas, na verdade, a quantidade de tempo que a equipe gasta na correção de regressão ou bugs introduzidos em cada iteração vai sofrer uma redução drástica. Você também pode fazer alterações em sua base de código com confiança, pois seu conjunto de testes vai ser capaz de garantir rapidamente que todos os recursos desenvolvidos anteriormente funcionem conforme o esperado.

Para escrever bons testes, você vai precisar certificar-se de que os desenvolvedores estejam envolvidos desde o início na definição das histórias de usuário. Esta é uma excelente forma de obter um entendimento mais compartilhado dos requisitos de negócios e facilitar o relacionamento com os gerentes de produto. Você pode até começar escrevendo os testes antes de implementar o código que os cumprirá.

Escreva testes ao corrigir erros

Quer você tenha uma base de código existente ou esteja apenas começando, é certo que haverá bugs ocorrendo como parte de seus lançamentos. Não se esqueça de adicionar testes ao resolver os bugs para impedir que eles voltem a ocorrer.

A CI permite que os engenheiros de QA escalem a qualidade

Outro papel que muda com a adoção de CI e automação é o papel do engenheiro de controle de qualidade. Ele não precisa mais testar de forma manual recursos comuns do aplicativo e agora pode dedicar mais tempo para fornecer ferramentas que apoiem desenvolvedores, além de ajudá-los a adotar as estratégias de teste corretas.

Assim que você começar a adotar a integração contínua, seus engenheiros de controle de qualidade poderão se concentrar em facilitar os testes com melhores ferramentas e conjuntos de dados, além de ajudar os desenvolvedores a crescer em sua capacidade de escrever códigos melhores. Ainda haverá alguns testes exploratórios para casos de uso complexos, mas esta deve ser uma parte menos proeminente de seu trabalho.

Integração contínua em cinco etapas

Você deve ter agora uma boa noção dos conceitos por trás da integração contínua, que podem ser resumidos aos seguintes pontos:

  1. Comece escrevendo testes para as partes cruciais do seu código de base.
  2. Obtenha um serviço de CI para executar esses testes de forma automática em cada push para o repositório principal.
  3. Assegure que a equipe integre as mudanças todos os dias.
  4. Corrija o build assim que for quebrado.
  5. Escreva testes para cada nova história que você implementar.

Embora possa parecer fácil, é preciso um real comprometimento de sua equipe para ser eficaz. Você deve desacelerar seus lançamentos no início, e precisa da adesão dos proprietários do produto para garantir que eles não apressem os desenvolvedores no envio de recursos sem testes.

Nossa recomendação é começar pequeno com testes simples para se acostumar com a nova rotina antes de prosseguir para a implementação de um conjunto de testes mais complexo que pode ser difícil de gerenciar.