Automação de Testes de Aceitação com Cucumber e JRuby

Propaganda
artigo
Automação de Testes de Aceitação com
Cucumber e JRuby
Aprenda a escrever especificações em linguagem natural executáveis e revolucione
a forma como você trabalha e desenvolve aplicações para seus usuários
Demetrius Nunes
([email protected]): formado em
Engenharia de Computação (PUC-Rio/2000).
Em 2004, se apaixonou por Ruby ao usar a
linguagem em sua dissertação de mestrado
na PUC-Rio. Certificado como ScrumMaster
em 2007, no seu dia-a-dia, tenta resolver o
máximo de “pepinos” para que os talentosos
desenvolvedores do TecGraf/PUC-Rio possam
“trabalhar em paz”.
36 www.mundoj.com.br
Dois graves problemas crônicos afligem projetos
de desenvolvimento de software nos dias de hoje:
documentação inexistente ou desatualizada e
testes de regressão manuais lentos e ineficientes.
Aprenda a se livrar desses dois males com uma
só tacada utilizando um processo orientado a
testes de aceitação automatizados através da
ferramenta Cucumber.
"SUJHPt"VUPNBÎÍPEF5FTUFTEF"DFJUBÎÍPDPN$VDVNCFSF+3VCZ
M
esmo com todo o barulho que se faz atualmente em torno
de TDD (Test Driven Development), esta importante prática
ainda não é parte da cultura da nossa indústria.
É aquela velha história: na hora do aperto, o que importa mesmo é código
escrito e rodando, certo? Escrever documentação? Depois a gente faz... Testes
de regressão automatizados? A gente dá uma “testadinha” agora pra ver se
está tudo bem e depois...
Só que o depois nunca chega e assim acumulamos o que chamamos de
dívida técnica. O pior é que essa dívida acumulada cobra “juros” pesados e
em pouco tempo, o ritmo de desenvolvimento chega àquele ponto em que
tudo o que a equipe faz é consertar bugs, que por sua vez introduzem novos
bugs, gerando um ciclo infindável de “conserta aqui-quebra ali” onde não há
mais a menor confiança na qualidade final do produto. Depois de um tempo,
a equipe de desenvolvimento não aguenta mais e se rebela, exigindo que a
Desenvolvimento orientado a testes de
aceitação automatizados
Não seria ótimo se ao final de cada iteração (ou “sprint”, assumindo que
você utiliza alguma metodologia iterativa, como Scrum) sua equipe de
fato entregasse mais um conjunto de funcionalidades, juntamente com
toda a documentação (principalmente as especificações funcionais) escrita e atualizada e com testes de aceitação automatizados que comprovam que o que foi implementado realmente está de acordo com o que
foi especificado, ou seja, acordado entre você e o usuário? Além disso,
não seria maravilhoso que, no apertar de um botão, você conseguisse
ver em alguns minutos todo o sistema sendo reexecutado automaticamente, passando por todas as funcionalidades já entregues nas iterações
anteriores, provando que nada que já funcionava deixou de funcionar?
Sonho, delírio, utopia? Essa visão não só é perfeitamente possível de
ser atingida, como deveria ser o padrão mínimo de qualidade e profissionalismo em nossa indústria. Para que isso ocorra, precisamos mudar
fundamentalmente a nossa forma de pensar na seguinte direção: o
tempo do desenvolvedor não pode e nem deve ser gasto praticamente
de forma integral na atividade de codificação de funcionalidades e/ou
correções de bugs. Existem outras atividades tão valiosas quanto a codificação que merecem um tempo considerável de dedicação da equipe
de desenvolvimento. Colocando de forma geral, essa seria a divisão de
gerência permita o famoso “reescrever do zero”.
Mas será que dessa vez a história será diferente? Afinal, o problema não foi
causado pela própria falta de profissionalismo da equipe? Claro que não! A
gerência é que foi a culpada, pois foi ela que concordou com aqueles prazos
impossíveis! Ou então foi culpa do usuário, que mudava de ideia a toda hora
e só sabia pedir mais e mais funcionalidades inúteis, certo?
Talvez sim, talvez não, mas se queremos realmente mudar nossos resultados,
temos que começar por nós mesmos, pois para podermos ser de fato considerados profissionais, não podemos abrir mão de todas as práticas e técnicas
necessárias para garantir a qualidade do nosso trabalho.
Ou você acha que um médico aceitaria não esterilizar seus instrumentos
ou deixaria de higienizar suas mãos antes de uma cirurgia por estar sendo
pressionado pelo hospital onde trabalha?
tempo que considero mais apropriada de acordo com o valor agregado
de cada atividade:
t OBFMBCPSBÎÍPEFFTQFDJmDBÎÜFTGVODJPOBJTFEPDVNFOUBÎÍP
técnica;
t OBBVUPNBÎÍPEFUFTUFTEFBDFJUBÎÍPRVFDPNQSPWFNPCPN
funcionamento do sistema;
t OP EFTJHO F DPEJmDBÎÍP EF GVODJPOBMJEBEFT F DPSSFÎÜFT EF
bugs;
t PVUSBTBUJWJEBEFT
Você pode estar se perguntando se gastar um quarto do tempo da equipe de desenvolvimento elaborando especificações funcionais realmente
vale a pena, pois pela nossa experiência, sabemos que no exato segundo
em que terminamos de escrever uma especificação, ela já está desatualizada e vai ficando cada vez mais desatualizada conforme o sistema
vai evoluindo e mudando. Afinal, quem tem tempo de ficar atualizando
todas as especificações já escritas cada vez que o cliente muda de ideia
sobre como o sistema deve funcionar? E quanto a mais 25% em automação de testes de aceitação? Não basta rodar o sistema manualmente e
ver que ele funciona de acordo com o que foi especificado?
Gastar metade do tempo da equipe realizando essas atividades parece
loucura, mas na verdade loucura é justamente não realizá-las, pois são
justamente essas duas atividades que produzirão as peças-chave para
manter o ritmo de desenvolvimento sustentável e a qualidade do siste-
37
"SUJHPt"VUPNBÎÍPEF5FTUFTEF"DFJUBÎÍPDPN$VDVNCFSF+3VCZ
ma no longo prazo. Afinal, quem vai garantir que todas as modificações introduzidas na última iteração não afetaram funcionalidades que já haviam
sido testadas e entregues? Para piorar, conforme o sistema vai crescendo
e se tornando mais complexo, testar novamente todo o sistema de forma
manual para garantir que nada deixou de funcionar (a isso denominamos
teste de regressão, pois com ele evitamos que o sistema “regrida”) vai adquirindo custos proibitivos até o ponto em que se torna inviável.
Especificações funcionais executáveis
utilizando Linguagem Gherkin
Uma especificação funcional escrita de forma tradicional, como, por
exemplo, um documento de texto estático, tem um valor agregado limitado, que como vimos acima, vai se depreciando conforme o sistema
evolui. Mas e se pudéssemos utilizar nossa especificação funcional ativamente de forma que ela sirva para verificar se o comportamento do sistema está de acordo com o que foi escrito? Idealmente, ao entregar uma
funcionalidade nova, deveríamos verificar que ela está perfeitamente
aderente ao que foi especificado, certo? Não seria ótimo se pudéssemos
automatizar essa verificação, passando este trabalho para a máquina,
que poderia executá-la muito mais rapidamente e bem mais frequente?
Para fazer isso, basta aprendermos a escrever uma especificação em
linguagem “Gherkin”, uma linguagem específica de domínio de negócios
(DSL), que podemos chamar de “pseudolinguagem natural”, pois, apesar
de aparentar ser um texto livre, ela segue uma estrutura conhecida como
visto na Listagem 1.
Listagem 1. Estrutura de uma especificação em linguagem Gherkin.
Dado que (pré-condição 1)
E que (pré-condição 2)
Quando (ação 1)
E (ação 2)
E (ação 3)
Então (pós-condição 1)
E (pós-condição 2)
E (pós-condição 3)
As palavras-chave Dado, Quando e Então servem para denominar, respectivamente, pré-condições, ações (ou eventos) e pós-condições (ou
expectativas). A conjunção E é apenas um recurso para evitar repetições
dessas palavras-chave e tornar o texto mais legível. Vejamos um exemplo
prático de uma funcionalidade de autenticação para uma aplicação de
ambiente desktop na Listagem 2.
O documento acima especifica como a funcionalidade de “Autenticação
por senha” deve funcionar. Ao menos, como o cenário de “Login bemsucedido” deve se comportar. Na prática, outros cenários devem ser
adicionados para tornar esta especificação realmente completa e abrangente (dependendo de nossos requisitos, poderíamos ter outros cenários, como, por exemplo: login malsucedido, campos não-preenchidos,
usuários desativados etc.).
O texto entre Funcionalidade e Cenário é apenas uma narrativa no
formato de “User Story” (Para que, Como, Eu quero) e serve apenas para
tornar o documento mais compreensível, como um cabeçalho. A linha
“# language: pt” servirá para informar ao Cucumber que a especificação
está em português. O comportamento do sistema é especificado de fato
38 www.mundoj.com.br
Listagem 2. Especificação para uma funcionalidade de Login em
um sistema desktop.
# language: pt
Funcionalidade: Autenticação por senha
Para garantir a segurança das informações do meu sistema
Como um usuário cadastrado
Eu quero ter que me autenticar com uma senha antes de ter acesso ao
sistema
Cenário: Login bem-sucedido
Dado que estou na tela de Login
Quando preencho o campo “Usuário” com “silva”
E preencho o campo “Senha” com “segredo”
E aperto o botão “Entrar”
Então devo ver a tela Principal
E devo ver a mensagem “Bem-vindo Sr. Silva!”
após o título do Cenário, utilizando a estrutura Gherkin.
Note como, apesar de estarmos seguindo uma estrutura gramatical fixa,
o texto produzido é perfeitamente compreensível para usuários finais
do sistema e pode ser validado por eles antes mesmo de começarmos a
escrever qualquer código.
Executando especificações Gherkin com
Cucumber
Para executar as especificações escritas em linguagem Gherkin, utilizaremos a ferramenta de BDD (Behaviour Driven Development) chamada
Cucumber (veja como instalar Cucumber no Quadro 1). Cucumber
é escrita em linguagem Ruby, mas pode ser utilizada para executar
especificações de aplicações escritas em qualquer linguagem, como
veremos adiante. Para que Cucumber possa executar as especificações,
as mesmas devem ser salvas em arquivos-texto com extensão “.feature”. É
aconselhável utilizar a seguinte estrutura de diretórios para isso:
$RAIZ_DA_APLICACAO
features/
login.feature
step_definitions/
support/
Por hora, vamos ignorar as pastas “step_definitions” e “support”, que
serão explicadas no próximo tópico. Salvando o conteúdo da Listagem
2 no arquivo “features/login.feature” (lembre-se de salvar o arquivo em
formato UTF-8), podemos digitar o comando visto na Listagem 3 numa
sessão de terminal a partir do diretório raiz da aplicação para que a especificação em “login.feature” seja executada pelo Cucumber.
Obviamente, conforme Listagem 3 houve uma falha ao tentar executar
esta especificação neste momento e vamos entender o resultado obtido.
Mas, antes, você deve estar se perguntando: como posso querer executar
a especificação se não escrevi nenhuma linha de código do sistema ainda?
Fizemos isso pois estamos seguindo a filosofia TDD (Test-Driven Development), em que primeiro escrevemos os testes (no nosso caso na forma de
especificações) e depois escrevemos o código da aplicação tendo como
objetivo único fazer com que os testes passem. Como especificamos o
"SUJHPt"VUPNBÎÍPEF5FTUFTEF"DFJUBÎÍPDPN$VDVNCFSF+3VCZ
Listagem 3. Resultado da tentativa de executar a especificação pelo Cucumber
$ jruby –S cucumber features/login.feature
# language: pt
Funcionalidade: Autenticação por senha
Para garantir a segurança das informações do meu sistema
Como um usuário cadastrado
Eu quero ter que me autenticar com uma senha antes de ter acesso ao
sistema
Cenário: Login bem sucedido
# features/login.feature:7
Dado que estou na tela de Login
# features/login.feature:8
Quando preencho o campo “Usuário” com “silva” # features/login.
feature:9
E preencho o campo “Senha” com “segredo”
# features/login.
feature:10
E aperto o botão “Entrar”
# features/login.feature:11
Então devo ver a tela Principal
# features/login.feature:12
E devo ver a mensagem “Bem-vindo Sr. Silva!” # features/login.
feature:13
1 scenario (1 undefined)
6 steps (6 undefined)
0m0.027s
You can implement step definitions for undefined steps with these snippets:
Dado /^que estou na tela de Login$/ do
pending
end
Quando /^preencho o campo “([^\”]*)” com “([^\”]*)”$/ do |arg1, arg2|
pending
end
Quando /^aperto o botão “([^\”]*)”$/ do |arg1|
pending
end
Então /^devo ver a tela Principal$/ do
pending
end
Então /^devo ver a mensagem “([^\”]*)”$/ do |arg1|
pending
end
sistema na forma de exemplos de comportamento (cenários), estamos
na verdade praticando BDD (Behaviour Driven Development). Ambas as
técnicas possuem resultados e vantagens similares.
Mas antes de escrever o código da aplicação, por estarmos escrevendo
os testes na forma de especificações em linguagem natural, temos que
primeiro dar um passo intermediário: ensinar ao Cucumber como de
fato executar os passos contidos no cenário. Fazemos isso “traduzindo” as frases em linguagem natural para comandos em linguagem de
programação.
Olhando o resultado obtido, vemos que o Cucumber tenta adiantar nosso trabalho fornecendo os pedaços de código em linguagem Ruby que
precisamos para ensiná-lo a executar os passos da especificação. O que
temos que fazer agora é simplesmente copiar e colar (substitua “Então”
por “Entao” quando fizer isso) esses “snippets” dentro de um arquivo com
extensão “.rb” dentro da pasta “step_definitions” (por exemplo “step_definitions/login_steps.rb”) e começar a substituir as palavras “pending”,
dentro de cada bloco, pelo código que realmente faz o que a frase em
linguagem natural está dizendo. Essa é a fase na qual realizamos a automação dos passos.
Portanto, o ciclo de desenvolvimento utilizando Cucumber como ferra-
menta de BDD segue de forma geral a seguinte sequência:
1. escrevemos a especificação em linguagem natural Gherkin;
2. executamos a especificação e vemos os passos pendentes;
3. traduzimos os passos em linguagem natural pendentes para código
executável;
4. executamos a especificação novamente e vemos os passos falharem;
5. escrevemos código da aplicação para fazer os passos passarem;
6. executamos a especificação novamente e vemos os passos passarem;
7. repetimos os passos 2 a 6 até que a especificação passe por completo.
Automatizando aplicações
Swinger e Jemmy
Swing
com
Para começarmos a traduzir os passos em linguagem natural e implementá-los através de código executável, precisamos de alguma biblioteca ou
ferramenta que sirva para simular ações de um usuário no sistema. Para
aplicações Web existem muitas opções de ferramentas e bibliotecas para
esse fim. Dentre as mais conhecidas estão Selenium, Watir e HtmlUnit.
Como especificamos um sistema desktop, iremos utilizar a biblioteca
Swinger. Swinger é uma biblioteca escrita em JRuby que oferece algumas
dezenas de passos e funções já implementados para a automação de
aplicações desenvolvidas em Java e Swing. “Por baixo dos panos”, Swinger
apoia-se sobre uma excelente biblioteca desenvolvida pela Sun chamada
Jemmy, criando uma fina camada de abstração em torno desta. Jemmy é
amplamente utilizada para automatizar os testes da IDE Netbeans, entre
outros projetos complexos.
A biblioteca Jemmy realiza duas funções básicas de forma bastante eficiente e elegante: permite encontrar qualquer componente Swing em uma
aplicação em execução sem que seja necessário o conhecimento do código interno da aplicação e permite manipular estes componentes como
se fosse o próprio usuário a fazê-lo. Mesmo que você não utilize JRuby,
Cucumber ou Swinger, aconselho fortemente a estudar esta biblioteca
para qualquer necessidade de automação de testes de aplicações Swing.
Para que possamos automatizar nossa aplicação através de Swinger, primeiro precisamos criar o ambiente de execução e carregar as bibliotecas
de apoio necessárias. Para isso, devemos criar dentro da pasta "support"
um arquivo chamado "env.rb". Cucumber sempre procura por este arquivo
e ele é o primeiro código a ser executado antes das especificações.
A primeira linha da Listagem 4 carrega a biblioteca Test::Unit, equivalente ao JUnit no mundo Ruby, para que possamos utilizar assertivas em
nossos passos de pós-condição do tipo "Então". A segunda linha carrega
a biblioteca Swinger. A terceira linha carrega o sistema a ser testado.
A linha "World(Test::Unit::Assertions)" garante que os comandos de assertivas estarão disponíveis como funções globais para implementação
dos passos.
O bloco "Before do" chama a função "main" de nossa aplicação antes de
cada cenário para que a aplicação seja de fato executada. Finalmente, o
bloco "After do" fecha a janela que ainda estiver aberta após o término da
execução de nossos cenários.
Com essa preparação básica do ambiente de execução das especificações, estamos prontos para implementar os passos de automação no
nossos sistema no arquivo 'step_definitions/login_steps.rb'.
39
"SUJHPt"VUPNBÎÍPEF5FTUFTEF"DFJUBÎÍPDPN$VDVNCFSF+3VCZ
Listagem 4. Preparando o ambiente de execução das especificações no
arquivo support/env.rb.
require ‘test/unit’ require File.dirname(__FILE__) + ‘/../../lib/swinger/lib/swinger’
require File.dirname(__FILE__) + ‘/../../dist/sistema.jar’
World(Test::Unit::Assertions)
Before do
import ‘sistema.Login’
Login.main([].to_java(:string))
end
After do
@container.close if @container
end
Utilizando Swinger podemos usar funções de ajuda como dialog, text_
field, button, label e frame para localizar os componentes de interface
que precisamos manipular, tornando o código de automação dos passos
vistos na Listagem 5 bastante simples e rápido de implementar.
Listagem 5. Passos automatizados utilizando funções de ajuda do Swinger
Dado /^que estou na tela de Login$/ do
@container = dialog(“Login”)
end
Quando /^preencho o campo “([^\”]*)” com “([^\”]*)”$/ do |campo, valor|
field = text_field(campo)
field.text = valor
end
Quando /^aperto o botão “([^\”]*)”$/ do |botao|
button = button(botao)
button.push
end
Entao /^devo ver a tela Principal$/ do
@container = frame(“Principal”)
assert @container.visible?
end
Entao /^devo ver a mensagem “([^\”]*)”$/ do |mensagem|
label = label(mensagem)
assert label.visible?
end
Instalando e utilizando Cucumber com JRuby
Para ter um ambiente em JRuby e Cucumber funcionando na sua máquina, é muito fácil, basta seguir os cinco passos a seguir:
1. Certifique-se que você possui o interpretador de Java no seu PATH
e que ele seja a versão 1.5 ou acima. Para isso, execute o seguinte
comando:
java –version.
2. Visite o site oficial de JRuby em jruby.org e faça o download da última versão oficial. No momento do fechamento desta edição, era a
1.3.1, mas a 1.4 estava prestes a ser lançada, qualquer uma servirá.
3. Extraia o JRuby para seu disco e adicione o subdiretório bin ao seu
PATH. Depois disto, execute o comando abaixo para se certificar que
tudo está funcionando:
jruby -v
4. Agora precisamos instalar Cucumber através do comando:
jruby -S gem install cucumber
5. Pronto! Para executar especificações de um projeto, utilize o comando:
jruby -S cucumber <diretorio ou arquivo .feature>
Quadro 1. Como instalar Cucumber e JRuby
Implementando passos em Cucumber
escritos em Java e outras linguagens
Eu adoro a linguagem Ruby por todo seu poder e elegância e
recomendo fortemente que você invista o tempo para aprendê-la
(ainda mais com a possibilidade de poder utilizá-la em cima da
JVM através de JRuby). Eu garanto que você irá se apaixonar ou
ao menos adotá-la como sua 2ª linguagem (depois de Java, claro).
package cukes;
Mas se Ruby ainda te assusta, não se preocupe, é possível aproveitar os benefícios da ferramenta Cucumber utilizando apenas
a linguagem Java (ou outra linguagem que possa ser executada
na JVM, tais como Groovy, Scala, Javascript etc.). Para isso, visite a
página do projeto Cuke4Duke em:
public class BellySteps {
private List<String> belly = new ArrayList<String>();
import cuke4duke.Given;
import java.util.List;
import java.util.ArrayList;
@Given(“eu tenho (\\d+) pepinos na minha barriga”)
public void bellyCukes(int cukes) {
for(int i = 0; i < cukes; i++) {
belly.add(“cukes”);
}
}
http://wiki.github.com/aslakhellesoy/cuke4duke
Veja um exemplo de implementação de um passo em Java:
}
Quadro 2. Não precisa saber Ruby para utilizar Cucumber.
40 www.mundoj.com.br
"SUJHPt"VUPNBÎÍPEF5FTUFTEF"DFJUBÎÍPDPN$VDVNCFSF+3VCZ
Repare que ainda não escrevemos nenhuma linha de código do nosso
sistema, mas já escrevemos o código de teste que irá utilizá-lo. Com isso,
fizemos um exercício de imaginar (ou projetar) a interface e as interações
do usuário com nosso sistema, o que torna bem mais fácil o processo de
implementar o sistema de fato.
O código-fonte do sistema em si é bastante simples para este exemplo e
fica aqui o exercício para o leitor fazer o download deste projeto a partir do
link listado na seção de referências e examiná-lo, além de poder executar
as especificações do sistema em seu próprio ambiente e vê-las passar.
Mesmo com essas vantagens apontadas, você pode se perguntar se vale
realmente a pena investir o tempo necessário para escrever as especificações utilizando a linguagem Gherkin e, principalmente, automatizar
cada passo descrito nas especificações. Outra vantagem não mencionada
acima e que aparece no médio e longo prazo é que conforme as primeiras
especificações são automatizadas, o custo de automação das próximas vai
diminuindo, tendendo a praticamente zero. Isso ocorre porque o vocabulário para descrever comportamentos em um sistema é mais limitado do que
imaginamos e com o tempo, os passos e suas respectivas automações são
reutilizados quase integralmente se assim desejarmos.
Portanto, acredite, é possível desenvolver sistemas com documentação
e testes de regressão automatizados, com velocidade e qualidade. Seus
clientes e usuários agradecem!
Referências
Considerações finais
Mesmo tendo usado um exemplo muito simples, implementamos de fato
uma funcionalidade de um sistema seguindo nossa proposta de processo
orientado por testes de aceitação automatizados, através das especificações executáveis utilizando Cucumber. E isso nos trouxe grandes vantagens sobre um processo de desenvolvimento mais tradicional:
1. teremos feito exatamente o que foi acordado com o usuário e nada
mais do que o necessário;
2. teremos documentação atualizada do comportamento do sistema;
3. teremos testes automatizados que garantem a aderência do sistema
às especificações e poderão ser executados toda vez que precisarmos realizar testes de regressão
Assim, conseguimos atingir sem maiores esforços nosso objetivo que
parecia tão “utópico”.
EU USO – Nick Sieger
Nick Sieger
é engenheiro da Engine Yard, trabalhando
no JRuby e liderando esforços para tornar
a máquina virtual Java uma plataforma de
implantação robusta e fácil de utilizar para
aplicações web desenvolvidas em Ruby e
Rails. Ele criou e ajuda a manter o adaptador
JDBC para ActiveRecord que o JRuby on Rails
usa para conectividade com bancos de dados,
assim como a ferramenta Warbler e a biblioteca
JRuby-Rack para o deploy em servidores de
aplicação Java. Ele mantém um blog sobre
tópicos relacionados com Ruby e JRuby no
endereço http://blog.nicksieger.com/.
t $ØEJHPGPOUFEPFYFNQMPWPDÐQPEFCBJYBSPDØEJHPGPOUFDPNQMFUPEBBQMJDBÎÍPEFFYFNQMP
EFTUFBSUJHPBUSBWÏTEPDPNBOEPBCBJYP²OFDFTTÈSJPUFS(JUIUUQHJUTDNDPN
JOTUBMBEP
em sua máquina:
HJUDMPOFHJUHJUIVCDPNEFNFUSJVTOVOFTDVDVNCFS@NVOEPKHJU
Não esqueça de ler e seguir as instruções contidas no arquivo README presente na raiz
do projeto.
t 3VCZIUUQXXXSVCZMBOHPSHFIUUQSVCZCSPSH
t +3VCZIUUQXXXKSVCZPSH
t $VDVNCFSIUUQDVLFTJOGP
t 4XJOHFSIUUQHJUIVCDPNEFNFUSJVTOVOFTTXJOHFS
t 8IBUhTJOBTUPSZ 1PSRVFFDPNPFTDSFWFS6TFS4UPSJFTEFRVBMJEBEF
IUUQEBOOPSUIOFU
whats-in-a-story
t $ØEJHP-JNQPQPS3PCFSU$.BSUJO&E"MGB#PPLT
t "VUPNBÎÍP EF CSPXTFST QBSB BQMJDBÎÜFT 8FC 4FMFOJVN IUUQTFMFOJVNIRPSH
8BUJS
IUUQXBUJSDPN
)UNM6OJU IUUQIUNMVOJUTPVSDFGPSHFOFU
F $FMFSJUZ IUUQDFMFSJUZ
SVCZGPSHFPSH
t /FUCFBOTF+FNNZIUUQXXXOFUCFBOTPSHFIUUQTKFNNZEFWKBWBOFU
Saber mais
Figura 1. Tela do sistema já implementado segundo as
especificações executáveis.
Na Edição 36 da Revista Mundoj, apresentamos
o artigo "Aplicações Desktop a jato com JRuby e
Netbeans", mostrando como construir uma aplicação Java para ambiente Desktop com Swing,
utilizando Netbeans, JRuby e o padrão MVP
(Model-View-Presenter) para garantir a testabilidade.
Para mim, o principal benefício de usar uma ferramenta como RSpec é clareza de intenção. Eu uso
exclusivamente RSpec para testar meu projeto open
source JRuby-Rack [1]. JRuby-Rack é um projeto que
mistura Java e Ruby, então faz sentido utilizar uma
ferramenta Ruby para testar ambos visto que existe
a necessidade de se testar código Ruby. No entanto,
muitos dos benefícios de clareza e expressividade
que tenho visto também podem ser aplicados para
projetos completamente feitos em Java.
1. A DSL interna do RSpec faz com que seja mais fácil escrever testes que declarem a sua intenção.
"Specdoc" fornece acesso a essa intenção numa
forma que pode ser compartilhada com pessoas que não estão familiarizadas com o código.
2. Uma linguagem maleável como Ruby faz com
que escrever testes compactos seja mais fácil
por meio da aplicação do princípio DRY (Don't
Repeat Yourself – "não se repita"), o reuso de
setup, teardown e lógica de fixture.
3. As características de integração com Java do
JRuby, tais como injeção automática de interface, permite que você possa utilizar objetos
Ruby como mocks para métodos Java.
O Cucumber leva essa clareza a um novo nível através
da união dos testes com a documentação. Suas user
stories e requisitos, sua documentação, são os testes.
Isso permite que você escreva testes juntamente com
um cliente ou especialista de domínio (interessado
no projeto) que não possua qualquer experiência em
programação. Mesmo que você não veja seu projeto
adotando Ruby ou RSpec como uma ferramenta de
testes, você deve fazer um favor a si mesmo e dar uma
olhada no Cucumber, o qual pode ser usado com Java
por meio do projeto Cuke4Duke [2].
[1]: http://jruby-rack.kenai.com/
[2]:http://wiki.github.com/aslakhellesoy/cuke4duke
41
Download