Utilizando Travis CI como servidor de integração contínua em projetos open-source: um exemplo com a linguagem Java
Quando falamos de qualidade em software, uma das grandes preocupações dos times de desenvolvimento é a verificação do impacto de novas funcionalidades, melhorias e correções no código-fonte, como parte da evolução do software. Essa fase de verificação de todo pacote de novas funcionalidades e melhorias implementadas, simulando o que vai estar em produção para o cliente, é conhecido como teste de integração.
Agora, imaginem gerenciar o teste dessas alterações, de uma vez só e não continuamente. Como descobrir com certa agilidade e antecedência, se as alterações ou novas funcionalidades não criaram novos defeitos no software? A resposta é: integração contínua.
Integração contínua (em inglês, Continuous Integration — CI) é uma prática de desenvolvimento de software de DevOps, baseada na integração freqüente do código em um repositório compartilhado. Essa prática veio da metodologia ágil eXtreme Programming (XP), criada por Kent Beck no ínicio dos anos 2000.
Basicamente, o conceito de CI é: um desenvolvedor, responsável por uma tarefa, cria o caso de teste, implementa o código e executa testes unitários. Em algum ponto de quebra conveniente, é decidido enviar essa alteração para o repositório principal. Se houver algum conflito com código base, esse conflito deve ser resolvido. Uma vez que as alterações forem enviadas e integradas ao código base, é preciso construir (fazer o build, na linguagem dev) esse “novo sistema”, para verificar a integridade do seu código. Se o build falhou, ou seja, a implementação afetou o funcionamento de algo, o desenvolvedor deve corrigir o bug. Se tudo correr bem, a alteração é liberada para a continuidade dos testes. A ideia principal é o monitoramento constante de alterações, mantendo a integração frequente do código.
In my early days in the software industry, one of the most awkward and tense moments of a software project was integration. The essence of this transformation is the practice of integrating more frequently. — Martin Fowler
Dentre os benefícios da integração contínua estão:
- Integridade do software: temos sempre a garantia de que o código compila e que todas as funcionalidades que foram testadas estão íntegras e funcionam como o esperado.
- Melhorias na produtividade do desenvolvedor: encoraja comportamentos que ajudam a reduzir o número de erros e bugs que podem ser percebidos pelo cliente.
- A equipe consegue encontrar bugs mais rapidamente: os testes ficam mais frequentes, permitindo descobrir e investigar erros mais cedo e evitando que problemas no software cresçam no futuro.
- Atualizações mais assertivas feitas mais rapidamente: a equipe consegue liberar versões mais assertivas para os clientes com maior frequência.
Essa integração pode ser feita de forma manual ou automatizada com ferramentas como Jenkins, Circle CI, Hudson e Travis CI, por exemplo. Nesse último texto da série sobre qualidade, vamos falar de integração contínua com o Travis CI e demonstrar como o seu uso pode facilitar o dia-a-dia da sua equipe.
Configurando o Travis CI em um projeto Java
O Travis CI é um serviço de integração contínua distribuído e disponível na nuvem, utilizado para criar e testar projetos de software hospedados no GitHub. Existem duas versões do Travis: uma free, em que qualquer projeto open-source pode ser testado e configurado de acordo com sua tecnologia específica; uma paga ou comercial, que possuem planos específicos para que equipes possam testar seus projetos privados.
Aqui, vamos exemplificar como configurar um projeto na versão free. O projeto escolhido foi artigo-solid-medium. Esse projeto contém as implementações dos exemplos demonstrados no artigo Princípios S.O.L.I.D: o que são e porque projetos devem utilizá-los. Vamos ao passo a passo:
- Primeiro passo a ser feito é logar no Travis CI com a sua conta do GitHub.
2. Após o login, devemos sincronizar os repositórios da sua conta. Feito isso, precisamos habilitar o Travis para o nosso repositório artigo-solid-medium.
3. Em seguida, precisamos criar um arquivo no diretório raiz do projeto chamado de .travis.yml.
É esse arquivo que o servidor vai procurar para identificar todas as configurações e permissões necessárias do ambiente de desenvolvimento do projeto que deve ser buildado, por exemplo: a linguagem de programação (Java, em nosso caso) e jdk (oraclejdk8). O Travis CI fornece uma documentação que pode ser consultada para criar uma configuração específica para cada tipo de projeto. A nossa configuração será a disponível abaixo:
4. O próximo passo é configurar o build automatizado. Para configurar a automação do processo e o gerenciamento das dependências, utilizei o Ant. Também criei um arquivo de propriedades, nomeado de build.properties, para armazenar os paths dos diretórios e pastas que serão referênciados no build.
Os buildfiles do Ant são escritos em XML. Cada buildfile contém a configuração de um único projeto e pelo menos uma tag target por padrão. Cada target contêm elementos. Cada elemento do buildfile pode ter um atributo id, e, posteriormente pode ser referido por um valor definido. Opcionalmente, uma descrição para o projeto pode ser fornecida como um elemento description no nível superior do arquivo.
Por exemplo, nosso primeiro target do arquivo é o clean e ele possui 4 tarefas a serem realizadas no início do build: deletar a pasta build, recriá-la e recriar os subdiretórios dela: classes e classes-test. Logo depois desse target temos outros relacionados às etapas de compilação e execução dos testes com JUnit, respectivamente.
Obs.: caso não sabia o que é e como criar testes com JUnit, temos esse artigo que pode lhe ajudar.
5. Com os arquivos essenciais já criados, prontos e testados localmente no projeto artigo-solid-medium, fazemos o commit da implementação. Como o repositório já estava habilitado no Travis CI, um build é disparado automaticamente, utilizando as configurações dos arquivos .travis.yml e build.xml que criamos nos passos anteriores.
6. Ao final do build, um e-mail é enviado com a notificação do resultado do build.
O resultado também pode ser visualizado no dashboard do projeto.
Na aba Branches, é possível monitorar os últimos builds realizados no projeto e seus respectivos resultados.
7. A cereja do bolo do Travis CI é que é possível exibir o status do build no GitHub! Tenho certeza que você já viu em algum repositório a flag build-passing e já se perguntou o que era e como colocar no seu projeto. Bom, agora você já sabe, parcialmente hehe!
É necessário colocar no arquivo README.md, geralmente na tag título, uma configuração semelhante a abaixo, apontando para a branch master do projeto:
[![Build Status](https://travis-ci.org/mariazevedo88/artigo-solid-medium.svg?branch=master)](https://travis-ci.org/mariazevedo88/artigo-solid-medium)
Após o commit da alteração, voilà! A informação se o build da branch principal do projeto passa ou não é exibida com sucesso. A medida que os builds são realizados, esse status é atualizado e exibido na página do projeto no GitHub.
Cabe ressaltar que você pode configurar quais branches terão esse acompanhamento contínuo e se pull requests também terão. É possível também adicionar outros passos como o uso de linters, para assegurar que as alterações estejam de acordo com o Java Code Coventions, por exemplo. Essa escolha dependerá do processo de desenvolvimento que a sua equipe adota.
Martin Fowler diz que uma das coisas interessantes sobre Integração Contínua é a frequência com que as pessoas se surpreendem com o impacto que ela causa em seus projetos, especialmente na qualidade do software e na visibilidade desta. Entretanto, sabemos que é um processo que vai além da visão técnica: é também cultural.
A chave para um processo de integração contínua bem feito é ter um ambiente de controle de versão centralizado e organizado, builds e testes automatizados. Cabe ressaltar também que ela é apenas um estágio inicial de um processo maduro de escalabilidade do desenvolvimento de software em uma empresa, que consiste em três fases: a Integração Contínua (Continuous Integration — já explicada no texto), a Entrega Contínua (Continuous Delivery — garantia de que um novo código está apto para ser disponibilizado em ambiente de produção e os deploys são aprovados de forma automática) e a Implantação Contínua (Continuous Deployment —garantia de que um novo código é disponibilizado automaticamente em ambiente de produção). Essas fases podem ser resumidas na imagem abaixo.
Como o escopo do texto é somente a fase de integração contínua, ambos os assuntos ficarão para uma próxima oportunidade. Lembrando que apesar do exemplo do texto ter sido um software Java, é possível criar um processo muito maduro e bacana em outras linguagens como JavaScript (com Node.js), Ruby, Python, dentre outros.
Caso ainda tenham dúvidas sobre como usar o Travis CI, deixe seu comentário ou mande um email.
Espero que tenham gostado do post. Abraços!
Referências
- eXtreme Programming: Rules. Site: http://www.extremeprogramming.org/rules.html
- Continuous Integration — Martin Fowler. Site: https://martinfowler.com/articles/continuousIntegration.html
- O que significa integração contínua? — Amazon. Site: https://aws.amazon.com/pt/devops/continuous-integration/
- Travis CI — Free projects. Site: https://travis-ci.org
- Travis CI — Private projects. Site: https://travis-ci.com/
- Apache Ant. Site: https://ant.apache.org/