Slides da palestra que seria ministrada no 38º GURU SP, evento promovido pelo grupo de usuários Ruby de São Paulo no dia 07 de novembro de 2015.
Nesta palestra, apresento os frameworks Cucumber e WebDriver, usados para automação de testes em aplicações web usando BDD.
[38º GURU SP] Automação de Testes Web em Ruby com Cucumber e Webdriver
1. www.qualister.com.br
(48) 4052-9536 / 9540
contato@qualister.com.br
Automação de Testes
Web em Ruby com
Cucumber e Webdriver
por Júlio de Lima
@juliodelimas
38º encontro do Guru-SP | São Paulo, 07 de novembro de 2015
2. Palestrante
Júlio de Lima
Especialista em teste de software com ênfase em automação de testes
de software, possui formação em Tecnologia da Informação e
certificações internacionais (CTFL e CTAL-TM pelo ISTQB) e nacional
(CBTS pela ALATS) relacionada a testes de software além de ser
certificado na ferramenta SoapUI Pro pela SmartBear Software.
Atualmente é consultor de automação de testes e instrutor na Qualister
e é professor de disciplina de teste de software em cursos de pós-
graduação no Paraná e em Santa Catarina.
julio.lima@qualister.com.br
twitter.com/juliodelimas
br.linkedin.com/in/juliodelimas
goldtips.by/juliodelimas
4. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
Cucumber
Especificação
dos Testes
Frameworks utilizados
4
Selenium
Webdriver
Driver
RSpec
Expectativas
5. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
Cucumber é um framework escrito em Ruby utilizado
para automação de testes de aceitação. Testes
escritos com Cucumber descrevem como a aplicação
deve se comportar.
A descrição dos comportamentos da aplicação pode
ser feitos em diversos idiomas, inclusive em
Português. Cucumber é escrito em Ruby, mas pode
ser utilizado em diversas linguagens de programação,
como: Java, C# e Python.
A descrição dos comportamentos da aplicação é
composta basicamente por Funcionalidade, Cenários
e Passos do cenário. Esta descrição é feita utilizando
Gherkin, um modelo de escrita compreendida pelo
Cucumber.
Cucumber
5
Cucumber
Especificação
dos Testes
6. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
O que o Cucumber pode fazer
▪ Escrever comportamentos do sistema em texto puro, em
diversos idiomas
▪ Testar classes e métodos Ruby, Java, C# e Python
▪ Executar testes a partir de linha de comando
▪ Integrar-se com ferramentas de integração contínua
▪ Gerar documentação dos comportamentos da aplicação
▪ Gerar relatórios de execução dos testes
Cucumber
6
Cucumber
Especificação
dos Testes
7. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
Gherkin é a sintaxe utilizada para escrever
funcionalidades no Cucumber. É um domínio
específico de linguagem para escrever regras de
negócio de fácil leitura
Sintaxe criada para ser utilizada por usuário técnicos e
não técnicos. Funcionalidades escritas no formato
Gherkin também são usadas como documentação do
sistema. Elas não detalham como a funcionalidade
deverá ser implementada.
Cada linha da descrição da funcionalidade é iniciada
por uma palavra chave e o escopo é definido
utilizando indentação. Funcionalidades em Gherkin
podem ser escritas em português ou em mais de 30
idiomas. Linhas podem ser comentadas utilizando “#”
no início da linha
Gherkin
7
Gherkin
DSL
8. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
Exemplo:
# language: pt
Funcionalidade: Descrição da funcionalidade desejada
Sendo alguém que será beneficiado
Posso utilizar uma funcionalidade do sistema
Para que possa alcançar um benefício para o negócio
Cenário: Uma situação de negócio
Dado que tenho uma precondição
Quando eu executo alguma ação
E executo alguma outra ação
Então recebo uma saída resultante das ações
executadas
Mas algo muda no estado atual do sistema
Gherkin
8
Gherkin
DSL
Daniel Wildt e Rafael Helm - Histórias de Usuário 3a Ed.(www.wildtech.com.br/historias-de-usuario/)
Introducing BDD | Dan North & Associates (dannorth.net/introducing-bdd/)
9. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
Os arquivos são salvos com a extensão .feature.
Funcionalidades podem ter múltiplos cenários e cada
cenário é iniciado pela palavra chave “Cenário”.
Cada cenário possui passos, sempre iniciados pelas
palavras chave: Dado, Quando, Então, E e Mas.
Gherkin
9
Gherkin
DSL
10. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
Selenium Webdriver é um framework de
automação de testes originalmente escrito em Java,
mas posteriormente disseminado em diversas
linguagens de programação.
Possui uma biblioteca completa de simulação de
ações do usuário sobre o browser, permitindo assim
automatizar estas ações.
O WebDriver conversa diretamente com um
browser real (Firefox, por padrão), por isso, há a
necessidade de tê-lo instalado na máquina.
O que é?
10
Selenium
Webdriver
Driver
11. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
O RSpec é um framework BDD (Behavior-Driven
Development), escrito em Ruby, utilizado para
estruturar os testes em ordem comportamental,
utilizando escrita em linguagem natural.
Ele também possui uma potente biblioteca de
expectativas e matchers, que é utilizada juntamente
com outros diversos frameworks de validação de
aplicações.
Usaremos ele em conjunto com os demais
frameworks para validar nossas aplicações.
O que é?
11
RSpec
Especificação
dos testes
13. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
Preparando o projeto
1. Crie o diretório C:GURUSPCucumber
2. Crie o diretório C:GURUSPCucumberfeatures
3. Crie o diretório C:GURUSPCucumberfeaturesstep_definitions
4. Crie o diretório C:GURUSPCucumberfeaturessupport
5. Instale o Bundler, um gerenciador de dependências, com gem install bundler
6. Execute o comando “bundle init” dentro do diretório Cucumber
Adicione as dependências ao Gemfile que foi gerado na raiz do projeto:
# A sample Gemfile
source "http://rubygems.org"
# gem "rails"
gem 'selenium-webdriver', '~> 2.48.1'
gem 'rspec-expectations', '~> 3.3.1'
gem 'cucumber', '~> 2.1.0'
8. Execute o comando "bundle install”
9. E então veremos o status abaixo:
Bundle complete! 3 Gemfile dependencies, 15 gems now
installed. 13
15. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
15
Hands-on
Crie dentro do diretório “features” um arquivo chamado
gerenciarMovimentacoes.feature” e adicione a ele o seguinte texto:
# language: pt
Funcionalidade: Gerenciar Movimentações
Sendo o administrador de uma loja
Posso gerenciar movimentações
Para que possa ver, de forma simples, as entradas e saídas de valores
Cenário: Gerando uma movimentação de entrada
Dado que eu esteja autenticado como administrador
E que eu tenha acessado o menu "Movimentações"
E clicado em "Nova movimentação” para inserir uma movimentação
Quando informar "Entrada" como tipo de movimentação
E informar "50,00" como valor da movimentação
E Informar "PlayStation e XBox" como itens da movimentação
E clicar em "Gravar"
Então verei a mensagem "Sucesso ao inserir a movimentação" como sucesso da operação
16. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
16
Hands-on
Agora, execute o comando cucumber --color na raiz do projeto e então
veremos como foi a execução dos cenários:
1 scenario (1 undefined)
8 steps (8 undefined)
0m0.062s
Serão gerados snippets de código para os cenários ainda não definidos, veja
um exemplo:
You can implement step definitions for undefined steps
with these snippets:
Dado(/^que eu esteja autenticado como administrador$/) do
pending # Write code here
end
17. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
17
Hands-on
O que faremos agora é criar um arquivo chamado "gerenciarMovimentacoes.rb" no diretório
“step_definitions" e então cole o snippet de código que foi copiado do console:
# encoding: utf-8
Dado(/^que eu esteja autenticado como administrador$/) do
pending # Write code here
end
Este método propõe que façamos login na aplicação que desejamos testar, então,
escreveremos comandos do Selenium Webdriver, que reproduzirão as ações do usuário,
começando por abrir o navegador, maximizar a tela e determinar um tempo máximo de
espera:
@navegador = Selenium::WebDriver.for :firefox
@navegador.manage.window.maximize
@navegador.manage.timeouts.implicit_wait = 5
O “@“ serve para fazer com que a variável possa navegar por todos os passos do nosso
teste.
Agora iremos navegar até a página inicial de nossa aplicação:
@navegador.get ‘http://localhost:4567/quickloja/'
18. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
18
Hands-on
E agora, preencher os campos do formulário de login e clicar no botão “Entrar" para
ter acesso ao interior da aplicação, veja:
@navegador.find_element(:id, 'usuariologin').send_keys("teste")
@navegador.find_element(:id, 'usuariosenha').send_keys("123")
@navegador.find_element(:css, ‘button[type="submit"]').click
Ótimo, já escrevemos o primeiro passo, antes de executá-lo precisamos criar um
arquivo “env.rb” no diretório “features/support" e adicionar a ele os requires para o
RSpec, Cucumber e Webdriver:
# encoding: utf-8
require 'cucumber/formatter/unicode'
require 'rspec/expectations'
require ‘selenium-webdriver'
Agora executaremos os cenários novamente:
cucumber --color
19. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
19
Hands-on
O resultado será a apresentação do primeiro passo em verde:
Dado que eu esteja autenticado como administrador
# features/step_definitions/gerenciarMovimentacoes.rb:3
E os demais em amarelo, uma vez que ainda não foram definidos. E o status geral
demonstrará o seguinte resultado:
1 scenario (1 undefined)
8 steps (7 undefined, 1 passed)
0m7.539s
O próximo passo é copiar o segundo passo e automatizar os testes que demonstram
que ele pode ser executado com sucesso, logo, copio o snippet para o arquivo
“gerenciarMovimentacoes.rb" e crio a automação para ele, veja:
Dado(/^que eu tenha acessado o menu "([^"]*)"$/) do |arg1|
pending # Write code here that turns the phrase above into
concrete actions
20. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
20
Hands-on
Este passo tem duas características diferentes, uma expressão regular e uma variável
que receberá o valor extraído por ela, veja:
Dado(/^que eu tenha acessado o menu "([^"]*)"$/) do |arg1|
pending # Write code here
end
Vamos renomear a variável “arg1" para “menu”. A variável menu possuirá o nome do
menu a ser clicado, então nosso código ficará assim:
Dado(/^que eu tenha acessado o menu "([^"]*)"$/) do |menu|
@navegador.find_element(:link_text, menu).click
end
Ao executar o teste agora, veremos que dois casos já foram executados, restando agora 7
passos indefinidos, okay, vamos ao próximo:
Dado(/^clicado em "([^"]*)" para inserir uma movimentação$/) do |
arg1|
pending # Write code here
end
21. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
21
Hands-on
Que ficará assim:
Dado(/^clicado em "([^"]*)" para inserir uma movimentação$/) do |botao|
@navegador.find_element(:link_text, botao).click
end
Agora restam 5 passos, vamos ao próximo:
Quando(/^informar "([^"]*)" como tipo de movimentação$/) do |arg1|
pending # Write code here
end
Que ficará assim:
Quando(/^informar "([^"]*)" como tipo de movimentação$/) do |tipo|
movimentacaotipo =
Selenium::WebDriver::Support::Select.new(@navegador.find_element(:name,
"movimentacaotipo"))
movimentacaotipo.select_by(:text, "Saída") # ou :index ou :value
end
Agora restam 4 passos, o próximo é:
Quando(/^informar "([^"]*)" como valor da movimentaçao$/) do |arg1|
pending # Write code here
end
22. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
22
Hands-on
Que ficará assim:
Quando(/^informar "([^"]*)" como valor da movimentação$/) do |valor|
@navegador.find_element(:name, "movimentacaovalor").send_keys(valor)
end
Agora restam 3 passos, vamos ao próximo:
Quando(/^Informar "([^"]*)" como itens da movimentação$/) do |itens|
pending # Write code here
end
Que ficará assim:
Quando(/^Informar "([^"]*)" como itens da movimentação$/) do |itens|
@navegador.find_element(:name, "movimentacaoitens").send_keys(itens)
end
Agora restam 2 passos, o próximo é:
Quando(/^clicar em "([^"]*)"$/) do |arg1|
pending # Write code here
end
23. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
23
Hands-on
Que ficará assim:
Quando(/^clicar em "([^"]*)"$/) do |botao|
@navegador.find_element(:css, ".btn.btn-primary").click
end
Vamos ao último passo:
Entao(/^verei a mensagem "([^"]*)" como sucesso da operação$/) do |arg1|
pending # Write code here
end
Que ficará assim:
Entao(/^verei a mensagem "([^"]*)" como sucesso da operação$/) do |msg|
expect(@navegador.find_element(:css, ".alert").text).to eq(msg)
@navegador.quit
end
Obs. Note que usamos o método “quit" para fechar o browser ao fim da execução, agora, ao executar
o teste teremos o seguinte resultado:
1 scenario (1 passed)
8 steps (8 passed)
0m12.360s
24. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
24
Gerar um relatório de execução no formato HTML
cucumber --format html --out relatorio.html
Hands-on
Saída:
26. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
26
Documentação da API do Cucumber
http://www.rubydoc.info/gems/cucumber/
Cucumber
Documentação da API do Selenium WebDriver
http://www.rubydoc.info/gems/selenium-
webdriver/0.0.28/Selenium/WebDriver
https://selenium.googlecode.com/svn/trunk/
docs/api/rb/Selenium/WebDriver.html
Relatórios de execução
27. www.qualister.com.brwww.qualister.com.br
Texto do Título
• Nível de Corpo Um
– Nível de Corpo Dois
• Nível de Corpo Três
– Nível de Corpo Quatro
» Nível de Corpo Cinco
27
Slides:
http://goo.gl/CgaaWo
Vídeo da palestra:
https://youtu.be/-W6335X4jno