Os dias de “cowboy coding” já se passaram em muitas organizações, substituídos por um renovado interesse na geração de softwares de qualidade. O teste de Integração contínua (CI) é um componente vital na prática de técnicas de programação ágil que leva ao software de alta qualidade. Conheça a teoria e a prática do teste de CI explorando o Buildbot, um sistema de CI de software livre baseado em Python.
A Integração contínua (CI) é um processo de desenvolvimento de software que promove os seguintes princípios:
- Manter um repositório de fonte isolada
- Automatizar a construção
- Tornar sua construção capaz de se autotestar
- Todos se cometem todos os dias
- Todo cometimento deve construir a linha principal em uma máquina de integração
- Manter a construção rápida
- Testar em um clone do ambiente de produção
- Facilitar para que todos obtenham o mais recente executável
- Todos podem ver o que está acontecendo
- Automatizar a implementação
Amplamente popularizado por Martin Fowler, a ideia básica da CI é testar e construir continuamente seu software em cada ramificação e também quando o código é mesclado no tronco. Isso leva a um aumento geral na integridade da base do código e também a um aumento na comunicação com os membros da equipe e a uma oportunidade de obter feedback sobre a qualidade geral do seu código. Frequentemente, as pessoas usam esse ciclo para gerar relatórios de cobertura do código e outras estatísticas.
O Buildbot, como outros sistemas de CI, ajuda a automatizar esse ciclo de registro, construção e teste. Os escravos do Buildbot geralmente são executados em plataformas como Win32, Solaris, Intelx64 etc.
O sistema pode enviar uma notificação por e-mail quando uma construção falha e manter um controle de todas as construções em execução, para que o desenvolvedor possa obter uma visão panorâmica de todo o processo. Finalmente, as pessoas frequentemente utilizam o ciclo automatizado para gerar métricas sobre a qualidade do seu software a qualquer momento. Ao final deste artigo, vamos tratar das métricas e por que faz sentido executá-las em um sistema de CI.
Introdução ao Buildbot
Antes de entrarmos nos elementos básicos do Buildbot, vamos dar uma olhada na sua arquitetura. Como mostra a Figura 1, existem essencialmente três camadas na parte superior do processo de construção. Há uma camada de controle de versão que se anexa a notificações de um sistema de controle de versão.
Existe também uma camada de construção que realiza a comunicação a partir do mestre de construção e retorna os resultados da construção. Finalmente, há a camada de notificação, que frequentemente é configurada para enviar e-mails, ou uma mensagem IRC, quando a construção falha ou para que uma página da Web exiba os resultados coletados das construções com o passar do tempo.
Figura 1. Visão geral da arquitetura do Buildbot
Um dos outros principais recursos da arquitetura do Buildbot é a dependência da biblioteca Twisted baseada em Python para identificar comunicação assíncrona entre mestres e escravos. Essa arquitetura baseada em retorno de chamada permite um loop de feedback mestre/escravo muito simples, embora robusto. Encontre mais detalhes sobre a biblioteca Twisted na seção Recursos ao final deste artigo.
Se você ainda não tiver ouvido falar sobre Buildbot, algumas pesquisas no Google revelarão uma grande coleção de mestres e escravos associados a grandes e pequenos projetos de software livre. Um escravo, que mencionei brevemente antes, é literalmente uma máquina escrava controlada pelo servidor Buildbot mestre.
Normalmente, um escravo é um dentre vários escravos e cada um é executado em uma plataforma de testes diferente. Esse é um importante conceito no mundo do servidor Buildbot. Por exemplo, é possível que você esteja na lista de e-mails de um projeto de software aberto e ouça alguém dizer, “Alguém quer oferecer uma máquina virtual para um escravo Windows”?
O projeto de linguagem Python usa uma grande coleção de escravos Buildbot para testar e construir continuamente a versão mais recente de Python em quantas plataformas for possível. A Figura 2 mostra uma grande variedade de máquinas executando esses escravos de construção do tronco Python, bem como testes. Com os recentes avanços em virtualização, atualmente é comum pedir a membros da sua comunidade de desenvolvimento que hospedem o escravo Buildbot, ou que simplesmente executem várias máquinas virtuais que emulam diferentes configurações de hardware.
Figura 2. Buildbot Python; consulte a figura ampliada
Outro usuário do Buildbot muito conhecido é o projeto do navegador Google Chrome. A Figura 3 mostra uma versão altamente customizada do Buildbot, que melhora significativamente a aparência e os recursos da interface do usuário do Buildbot. Felizmente, o Google transformou essas melhorias em software livre para o Buildbot. Ao final do artigo, consulte a seção Recursos a seguir, é possível obter a fonte e a construção dessa versão customizada.
Figura 3. Buildbot aprimorado pelo Google Chrome; veja a figura ampliada
A construção dessa configuração específica está fora do escopo deste artigo, mas recomendo que você dê uma olhada por conta própria. Agora, vamos fazer com que o servidor mestre Buildbot seja executado rapidamente.
Configurando o Buildbot em cinco minutos
Essas etapas foram executadas no Ubuntu 8.10, mas devem funcionar na maioria das distribuições Linux:
- Faça o download do ez_setup.py:
wget http://peak.telecommunity.com/dist/ez_setup.py - Instale o easy_install:
sudo python ez_setup.py - Instale o pacote Twisted Python com apt-get:
sudo apt-get install python-Twisted - Siga esta “receita” do collective.buildbot:
sudo easy_install collective.buildbot
Neste momento, começarão a aparecer várias coisas como o download e
a instalação automáticos de um grupo pacotes. Quando isso for concluído,
você estará pronto para criar um Buildbot! Se a instalação ocorrer
corretamente, digite na linha de comando do shell:
$ paster create -t buildbot my.project
$ cd my.project
Já está quase acabando, é sério, mas antes de terminar, deixe-me
apontar algumas armadilhas que podem enganá-lo quando você configurar o
Buildbot pela primeira vez. Dentro do seu arquivo
my.project/master.cfg, você verá algo como:
Listagem 1. Conteúdo de master.cfg
[buildout] master-parts = master passing.project
# uncomment this to enable polling
poller [master] recipe = collective.buildbot:master
project-name = passing.project
project # allow to force build with the web interface allow-force = true
# internal port port = 9051 # http port wport = 9081 # buildbot url.
change this if you use a
virtualhost url = http://localhost:9081/ # static files public-html =
${buildout:directory}/public_html slaves = localhost
NaOaPSWb [passing.project]
recipe = collective.buildbot:project slave-names = localhost
vcs = hg repositories =
/home/ngift/myhgrepo
# notifications mail-host = localhost email-notification-sender
= buildbot@cortese email-notification-recipient = super@example.com
# run test each
hour periodic-scheduler=60
# cron build cron-scheduler = 0 8 * * *
# You can change the sequences to build / test your app
# default options should work for most buildout based
projects build-sequence =
# /usr/bin/python2.5 bootstrap.py -c project.cfg
# /usr/bin/python2.5 bin/buildout -c project.cfg test-sequence =
nosetests # zope.testing require exit with status
# bin/test --exit-with-status
[poller] recipe = collective.buildbot:poller
# don't forget to check this # since
it's generated from the paster template it may be a
wrong url repositories = /home/ngift/myhgrepo
#user = h4x0r #password = passwd poll-interval = 120
As coisas mais importantes que devem ser verificadas inicialmente são:
- você tem o repositório de controle de origem apropriado
- você deixou build-sequence em branco inicialmente
- seu test-sequence, “nose” no meu caso, passará nos testes quando o código for depurado no repositório fornecido.
Caso você tenha outras dúvidas, procure collective.buildbot no guia de Recursos e obtenha um link. Depois que seu arquivo de configuração tiver sido configurado, basta executar os dois comandos a seguir:
$ python bootstrap.py
$ ./bin/buildout
Quando você executar o comando buildout, obterá algumas saídas que serão semelhantes a isto:
Listagem 2. Saída do comando buildout
{673} > ./bin/buildout Unused options for buildout: 'master-parts'.
Installing master. New python executable in /home/ngift/my.project Installing
setuptools............done. [output suppressed for space]
Quando esse comando terminar, a instalação do Buildbot estará concluída e você estará pronto para fazer as coisas funcionarem. Inicie ambos os daemons do Buildbot executando os seguintes comandos a partir do shell:
$ ./bin/master start $ ./bin/yourhostname start
Em seguida, se você apontar um navegador para a URL definida no arquivo master.cfg que, por padrão, é http://localhost:9081/, verá seu Buildbot novinho. No início, ele não fará muitas coisas. No entanto, se você fornecer a ele um script de construção e um executor de testes, ele irá depurar, construir e testar seu código automaticamente. Depois você deverá buscar algumas opções de configuração, mas o trabalho duro em si já está feito.
Gerando relatórios de métricas de código
Um recente desenvolvimento intelectual dos “nerds de testes” é aproveitar o ciclo de integração contínua para gerar também métricas sobre o código de origem. Uma das técnicas mais populares é executar o coletor de testes nosetest com a opção de cobertura. Se você tivesse um projeto chamado “foo”, normalmente executaria:
nosetests –with-coverage –cover-package=example –cover-html \
–cover-html-dir=example_report.html test_example.py
Isso geraria um relatório HTML mostrando todas as linhas de código que não foram cobertas, juntamente com a saída para fluxos padrão, semelhante à listagem abaixo:
Listagem 3. Saída de nosetest
nglep%
nosetests --with-coverage --cover-package=example
--cover-html-dir=example_report.html test_example.py .
Name Stmts Exec Cover Missing
--------------------------------------- example 2 2 100%
----------------------------------------------------------------------
Ran 1 test in
0.004s OK
É possível fazer o download de example.py e test_example.py. A execução desse relatório todas as vezes que o código é revisado fornece ao desenvolvedor e ao gerenciador metadados sobre o que está realmente acontecendo no código. Esse é um exemplo perfeito do motivo pelo qual executar métricas simultaneamente à CI pode ser vantajoso para um projeto.
Outra ferramenta de métrica que fornece metadados sobre seu código é a classificação McCabe da PyMetrics. Nos anos 70, Thomas McCabe surgiu com uma simples e engenhosa observação sobre códigos: quanto mais complexo for um trecho de código, com mais frequência ele irá falhar. Embora isso possa parecer óbvio, infelizmente muitos desenvolvedores parecem não entender a ligação. Ao usar a ferramenta de linha de comando PyMetrics, é possível determinar o número total de ramificações por função.
Geralmente, você deseja manter o número de ramificações inferior a 10 em todos os métodos ou funções que cria, pois independentemente do momento, é difícil manter mais de sete ou oito coisas contextualizadas no cérebro humano. Como ponto de referência, basicamente não é possível testar/manter códigos com classificação superior a 50.
Pessoalmente, vi código com classificação 140 em produção, e o código era muito ruim o que, de fato, valida a teoria de McCabe. Se você puder capturar e sinalizar esse código complexo e frágil no início do processo de desenvolvimento, ele nunca entrará em produção, ainda que todos os testes sejam aprovados.
Conclusão
O principal benefício da integração contínua é a capacidade de otimizar o ciclo de garantia de qualidade com construções automatizadas de software, juntamente com testes e, opcionalmente, métricas de software. Essas construções são acionadas a cada alteração da origem e fornecem feedback instantâneo e relatórios para todo o projeto. Quando a CI é configurada corretamente, ela se torna de fato integrada no processo de produção do código, tanto quanto na criação do código em si.
O Buildbot não é a única alternativa para testes de CI. Dê também uma olhada nas ferramentas Hudson e Bitten. Cada uma delas permite a customização com plug-ins em Python, ainda que Hudson tenha sido escrito em Python. Consulte os recursos a seguir para obter mais informações sobre esses sistemas.
Recursos
Para Aprender:
- Leia o artigo de Martin Fowler sobre Integração Contínua
- A Wikipédia oferece uma introdução sobre testes de integração contínua
- A documentação essencial da biblioteca Twisted oferece uma visão geral e um tutorial sobre a estrutura Twisted
- O artigo Cobertura de instruções para Python introduz e explica o módulo de cobertura Python coverage.py.
- David Stanek discute a medição de Complexidade Ciclomática Python
- “O artigo Using Python to create UNIX command line tools”
(developerWorks, março de 2008) discute como criar ferramentas de linha
de comando em Python para administradores e desenvolvedores - “O artigo Planejando Ágil na Vida Real” (developerWorks, abril de 2009)
fornece raras orientações para fazer com que o desenvolvimento ágil
funcione na sua empresa - “Automation for the people” é uma série do developerWorks – orientada
para desenvolvedores Java, mas facilmente aplicável a qualquer
linguagem – que abrange diversas formas de automatizar e otimizar vários
aspectos do processo de desenvolvimento de software. - Também destinada a desenvolvedores Java, o artigo “Spot defects early
with Continuous Integration” (developerWorks, novembro de 2007) fornece
uma visão geral da CI - Na zona Linux do developerWorks, encontre centenas de artigos e
tutoriais, bem como downloads, fóruns de discussão e muitos outros
recursos para desenvolvedores e administradores Linux
Obter produtos e tecnologias:
- Obtenha a fonte do Buildbot do Google Chrome
- Para obter alternativas em relação ao Buildbot, confira as ferramentas Hudson e Bitten
- Saiba mais sobre a estrutura de testes nose
- O site collective.buildbot oferece uma coleção de receitas “buildout” do Buildbot
- PyMetrics é uma ferramenta para gerar uma Classificação de Complexidade Ciclomática
- Avalie os produtos da IBM da forma que melhor lhe convém: Faça o
download de uma versão de teste de produto, experimente um produto
on-line, use um produto em um ambiente de nuvem ou passe algumas horas
no SOA Sandbox aprendendo como implementar Arquitetura Orientada a
Serviço de forma eficiente
Artigo publicado originalmente em developerWorks Brasil, por Noah Gift
Noah Gift é o coautor do livro Python For UNIX and Linux System Administration pela O’Reilly, e também está trabalhando no livro Google App Engine In Action para a Manning. Ele é autor, palestrante, consultor e líder de comunidades, escrevendo para publicações como Red Hat Magazine, O’Reilly e MacTech. O site da sua empresa de consultoria é http://www.giftcs.com, e grande parte de suas obras pode ser encontrada em http://noahgift.com.
Noah tem mestrado em CIS pela Cal State Los Angeles e Bacharelado em Ciências Nutricionais pela Cal Poly San Luis Obispo. Ele é administrador de sistemas certificado pela Apple e pela LPI e trabalhou em empresas como Caltech, Disney Feature Animation, Sony Imageworks, Turner Studios e Weta Digital.