RSpec Best Friends
Mauro quem...
maurogeorge.com.br
RSpec
RSpec 
descrevendo melhor os testes
spec/models/pokemon_spec.rb 
it 'exibe o nome e o id nacional' do 
pokemon = Pokemon.new(nome: 'Charizard', id_nacional: 6...
spec/models/pokemon_spec.rb 
describe '#nome_completo' do 
it 'exibe o nome e o id nacional' do 
pokemon = Pokemon.new(nom...
RSpec 
definindo o sujeito
spec/models/pokemon_spec.rb 
context 'quando possui nome e o id nacional' do 
before do 
@pokemon = Pokemon.new(nome: 'Cha...
spec/models/pokemon_spec.rb 
context 'quando possui nome e o id nacional' do 
let(:pokemon) do 
Pokemon.new(nome: 'Chariza...
spec/models/pokemon_spec.rb 
context 'quando possui nome e o id nacional' do 
subject do 
Pokemon.new(nome: 'Charizard', i...
RSpec 
ordem aleatória nos testes
spec/spec_helper.rb 
RSpec.configure do |config| 
# ... 
config.order = "random" 
end
Testes que acessam rede
Testes que acessam rede 
introdução 
Testes lentos 
Testes quebradiços 
Não poder testar sem rede
app/services/criador_pokemon.rb 
class CriadorPokemon 
# ... 
def criar 
Pokemon.create(nome: nome) 
end 
! 
private 
# .....
spec/services/criador_pokemon_spec.rb 
describe 'pokemon criado' do 
before do 
criador_pokemon.criar 
end 
! 
subject do ...
Testes que acessam rede 
vcr
Testes que acessam rede 
vcr: configuração
spec/support/vcr.rb 
VCR.configure do |c| 
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes' 
c.hook_into :webmock 
e...
Testes que acessam rede 
vcr: feedback rápido
bash 
Failure/Error: CriadorPokemon.new(6) 
VCR::Errors::UnhandledHTTPRequestError: 
! 
! 
===============================...
Testes que acessam rede 
vcr: forjando a resposta
spec/services/criador_pokemon_spec.rb 
describe 'pokemon criado' do 
before do 
VCR.use_cassette('CriadorPokemon/criar') d...
Testes que acessam rede 
vcr: RSpec metadata
spec/support/vcr.rb 
VCR.configure do |c| 
! 
# ... 
c.configure_rspec_metadata! 
end 
spec/spec_helper.rb 
RSpec.configur...
spec/services/criador_pokemon_spec.rb 
describe 'pokemon criado', :vcr do 
before do 
criador_pokemon.criar 
end 
! 
#... ...
factory_girl
factory_girl 
fixtures X factories
factory_girl 
criando uma factory
spec/factories/usuarios.rb 
FactoryGirl.define do 
factory :usuario do 
nome 'Mauro' 
email 'mauro@helabs.com.br' 
end 
en...
console rails 
FactoryGirl.create(:usuario) 
FactoryGirl.create(:usuario, email: 'mauro@helabs.com.br')
factory_girl 
configurando
spec/spec_helper.rb 
RSpec.configure do |config| 
# ... 
config.include FactoryGirl::Syntax::Methods 
end 
Em um teste qua...
factory_girl 
attributes_for
spec/controllers/posts_controller_spec.rb 
describe "POST 'create'" do 
let(:params) do 
{ 
artigo: { 
titulo: 'Meu titulo...
spec/controllers/posts_controller_spec.rb 
describe "POST 'create'" do 
let(:params) do 
{ artigo: attributes_for(:artigo)...
factory_girl 
herança
spec/factories/artigos.rb 
factory :artigo do 
titulo 'Diversas dicas do RSpec' 
conteudo 'Conteúdo de Diversas dicas do R...
console rails 
FactoryGirl.create(:artigo_aprovado) 
FactoryGirl.create(:artigo_nao_aprovado)
factory_girl 
traits
spec/factories/artigos.rb 
factory :artigo do 
titulo 'Diversas dicas do RSpec' 
conteudo 'Conteúdo de Diversas dicas do R...
console rails 
FactoryGirl.create(:artigo, :aprovado) 
FactoryGirl.create(:artigo, :nao_aprovado)
factory_girl 
associações
console rails 
usuario = FactoryGirl.create(:usuario) 
FactoryGirl.create(:artigo, usuario: usuario)
spec/factories/artigos.rb 
factory :artigo do 
titulo 'Diversas dicas do RSpec' 
conteudo 'Conteúdo do artigo' 
usuario 
e...
factory_girl 
strategies
console rails 
pokemon = FactoryGirl.build(:pokemon)
console rails 
pokemon = FactoryGirl.build_stubbed(:pokemon)
timecop
app/models/pokemon.rb 
class Pokemon < ActiveRecord::Base 
! 
! 
scope :escolhidos_ontem, -> do 
where(escolhido_em: 1.day...
spec/models/pokemon_spec.rb 
describe '.escolhidos_ontem' do 
let!(:pokemon_escolhido_ontem) do 
create(:pokemon, escolhid...
spec/models/pokemon_spec.rb 
describe '.escolhidos_ontem' do 
! 
# ... 
! 
it 'tem o pokemon escolhido ontem' do 
Timecop....
simplecov
simplecov 
verificando a cobertura
spec/spec_helper.rb 
require 'simplecov' 
SimpleCov.start 'rails' 
Primeira linha do 
spec_helper.rb
simplecov 
O falso 100%
app/models/pokemon.rb 
class Pokemon < ActiveRecord::Base 
! 
validates :nome, :id_nacional, presence: true 
scope :escolh...
simplecov 
Não teste associações, validações ou 
escopos do Active Record
simplecov 
teste associações, validações e escopos do 
Active Record
simplecov 
devo ter 100% de cobertura de testes?
shoulda-matchers
app/models/pokemon.rb 
class Pokemon < ActiveRecord::Base 
! 
validates :nome, :id_nacional, presence: true 
validates :id...
spec/models/pokemon_spec.rb 
describe 'validações' do 
! 
it { is_expected.to validate_presence_of(:nome) } 
it { is_expec...
shoulda-matchers 
os matchers 
ActiveModel 
ActiveRecord 
ActionController
shoulda-matchers 
além do shoulda-matchers 
https://github.com/bmabey/email-spec 
https://github.com/philostler/rspec-side...
Obrigado!
maurogeorge.com.br
RSpec Best Friends @ Rupy Natal 2014
RSpec Best Friends @ Rupy Natal 2014
RSpec Best Friends @ Rupy Natal 2014
RSpec Best Friends @ Rupy Natal 2014
Próximos SlideShares
Carregando em…5
×

RSpec Best Friends @ Rupy Natal 2014

763 visualizações

Publicada em

Nesta palestra veremos:

- Boas práticas ao escrever testes utilizando o RSpec
- Como escrever testes que acessam rede utilizando o VCR e o WebMock
- Apresentando o factory_girl, comparando com as fixtures. E diversas dicas do factory_girl
- Testes que dependem de data utilizando o timecop
- Coverage de testes com o Simplecov e se devemos ou não atingir os 100% de cobertura de testes
- Evitando repetições durante os testes utilizando de matchers

Publicada em: Tecnologia
0 comentários
4 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

Sem downloads
Visualizações
Visualizações totais
763
No SlideShare
0
A partir de incorporações
0
Número de incorporações
110
Ações
Compartilhamentos
0
Downloads
5
Comentários
0
Gostaram
4
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

RSpec Best Friends @ Rupy Natal 2014

  1. 1. RSpec Best Friends
  2. 2. Mauro quem...
  3. 3. maurogeorge.com.br
  4. 4. RSpec
  5. 5. RSpec descrevendo melhor os testes
  6. 6. spec/models/pokemon_spec.rb it 'exibe o nome e o id nacional' do pokemon = Pokemon.new(nome: 'Charizard', id_nacional: 6) expect(pokemon.nome_completo).to eq('Charizard - 6') end
  7. 7. spec/models/pokemon_spec.rb describe '#nome_completo' do it 'exibe o nome e o id nacional' do pokemon = Pokemon.new(nome: 'Charizard', id_nacional: 6) expect(pokemon.nome_completo).to eq('Charizard - 6') end end
  8. 8. RSpec definindo o sujeito
  9. 9. spec/models/pokemon_spec.rb context 'quando possui nome e o id nacional' do before do @pokemon = Pokemon.new(nome: 'Charizard', id_nacional: 6) end ! it 'exibe o nome e o id nacional' do expect(@pokemon.nome_completo).to eq('Charizard - 6') end end
  10. 10. spec/models/pokemon_spec.rb context 'quando possui nome e o id nacional' do let(:pokemon) do Pokemon.new(nome: 'Charizard', id_nacional: 6) end ! it 'exibe o nome e o id nacional' do expect(pokemon.nome_completo).to eq('Charizard - 6') end end
  11. 11. spec/models/pokemon_spec.rb context 'quando possui nome e o id nacional' do subject do Pokemon.new(nome: 'Charizard', id_nacional: 6) end ! it 'exibe o nome e o id nacional' do expect(subject.nome_completo).to eq('Charizard - 6') end end
  12. 12. RSpec ordem aleatória nos testes
  13. 13. spec/spec_helper.rb RSpec.configure do |config| # ... config.order = "random" end
  14. 14. Testes que acessam rede
  15. 15. Testes que acessam rede introdução Testes lentos Testes quebradiços Não poder testar sem rede
  16. 16. app/services/criador_pokemon.rb class CriadorPokemon # ... def criar Pokemon.create(nome: nome) end ! private # ... def cria_info resposta = Net::HTTP.get(endpoint) @info = JSON.parse(resposta) end end
  17. 17. spec/services/criador_pokemon_spec.rb describe 'pokemon criado' do before do criador_pokemon.criar end ! subject do Pokemon.last end ! it 'possui o nome correto' do expect(subject.nome).to eq('Charizard') end end
  18. 18. Testes que acessam rede vcr
  19. 19. Testes que acessam rede vcr: configuração
  20. 20. spec/support/vcr.rb VCR.configure do |c| c.cassette_library_dir = 'spec/fixtures/vcr_cassettes' c.hook_into :webmock end
  21. 21. Testes que acessam rede vcr: feedback rápido
  22. 22. bash Failure/Error: CriadorPokemon.new(6) VCR::Errors::UnhandledHTTPRequestError: ! ! ===================================================================== An HTTP request has been made that VCR does not know how to handle: GET http://pokeapi.co/api/v1/pokemon/6/ ! There is currently no cassette in use. There are a few ways you can configure VCR to handle this request: ! ...
  23. 23. Testes que acessam rede vcr: forjando a resposta
  24. 24. spec/services/criador_pokemon_spec.rb describe 'pokemon criado' do before do VCR.use_cassette('CriadorPokemon/criar') do criador_pokemon.criar end end ! #... ! it 'possui o nome correto' do expect(subject.nome).to eq('Charizard') end end
  25. 25. Testes que acessam rede vcr: RSpec metadata
  26. 26. spec/support/vcr.rb VCR.configure do |c| ! # ... c.configure_rspec_metadata! end spec/spec_helper.rb RSpec.configure do |config| ! # ... config.treat_symbols_as_metadata_keys_with_true_values = true end
  27. 27. spec/services/criador_pokemon_spec.rb describe 'pokemon criado', :vcr do before do criador_pokemon.criar end ! #... ! it 'possui o nome correto' do expect(subject.nome).to eq('Charizard') end end
  28. 28. factory_girl
  29. 29. factory_girl fixtures X factories
  30. 30. factory_girl criando uma factory
  31. 31. spec/factories/usuarios.rb FactoryGirl.define do factory :usuario do nome 'Mauro' email 'mauro@helabs.com.br' end end
  32. 32. console rails FactoryGirl.create(:usuario) FactoryGirl.create(:usuario, email: 'mauro@helabs.com.br')
  33. 33. factory_girl configurando
  34. 34. spec/spec_helper.rb RSpec.configure do |config| # ... config.include FactoryGirl::Syntax::Methods end Em um teste qualquer let!(:artigo) do create(:artigo) end
  35. 35. factory_girl attributes_for
  36. 36. spec/controllers/posts_controller_spec.rb describe "POST 'create'" do let(:params) do { artigo: { titulo: 'Meu titulo', conteudo: 'Conteudo do artigo' } } end end
  37. 37. spec/controllers/posts_controller_spec.rb describe "POST 'create'" do let(:params) do { artigo: attributes_for(:artigo) } end end
  38. 38. factory_girl herança
  39. 39. spec/factories/artigos.rb factory :artigo do titulo 'Diversas dicas do RSpec' conteudo 'Conteúdo de Diversas dicas do RSpec' ! factory :artigo_aprovado do aprovado true end ! factory :artigo_nao_aprovado do aprovado false end end
  40. 40. console rails FactoryGirl.create(:artigo_aprovado) FactoryGirl.create(:artigo_nao_aprovado)
  41. 41. factory_girl traits
  42. 42. spec/factories/artigos.rb factory :artigo do titulo 'Diversas dicas do RSpec' conteudo 'Conteúdo de Diversas dicas do RSpec' ! trait :aprovado do aprovado true end ! trait :nao_aprovado do aprovado false end end
  43. 43. console rails FactoryGirl.create(:artigo, :aprovado) FactoryGirl.create(:artigo, :nao_aprovado)
  44. 44. factory_girl associações
  45. 45. console rails usuario = FactoryGirl.create(:usuario) FactoryGirl.create(:artigo, usuario: usuario)
  46. 46. spec/factories/artigos.rb factory :artigo do titulo 'Diversas dicas do RSpec' conteudo 'Conteúdo do artigo' usuario end
  47. 47. factory_girl strategies
  48. 48. console rails pokemon = FactoryGirl.build(:pokemon)
  49. 49. console rails pokemon = FactoryGirl.build_stubbed(:pokemon)
  50. 50. timecop
  51. 51. app/models/pokemon.rb class Pokemon < ActiveRecord::Base ! ! scope :escolhidos_ontem, -> do where(escolhido_em: 1.day.ago.midnight..Time.zone.now.midnight) end end
  52. 52. spec/models/pokemon_spec.rb describe '.escolhidos_ontem' do let!(:pokemon_escolhido_ontem) do create(:pokemon, escolhido_em: Time.zone.local(2014, 10, 16, 16, 50)) end ! subject do Pokemon.escolhidos_ontem end ! it 'tem o pokemon escolhido ontem' do expect(subject).to include(pokemon_escolhido_ontem) end end
  53. 53. spec/models/pokemon_spec.rb describe '.escolhidos_ontem' do ! # ... ! it 'tem o pokemon escolhido ontem' do Timecop.freeze(Time.zone.local((2014, 10, 16, 16, 50)) do expect(subject).to include(pokemon_escolhido_ontem) end end end
  54. 54. simplecov
  55. 55. simplecov verificando a cobertura
  56. 56. spec/spec_helper.rb require 'simplecov' SimpleCov.start 'rails' Primeira linha do spec_helper.rb
  57. 57. simplecov O falso 100%
  58. 58. app/models/pokemon.rb class Pokemon < ActiveRecord::Base ! validates :nome, :id_nacional, presence: true scope :escolhidos_ontem, -> do where(escolhido_em: 1.day.ago.midnight..Time.zone.now.midnight) end end
  59. 59. simplecov Não teste associações, validações ou escopos do Active Record
  60. 60. simplecov teste associações, validações e escopos do Active Record
  61. 61. simplecov devo ter 100% de cobertura de testes?
  62. 62. shoulda-matchers
  63. 63. app/models/pokemon.rb class Pokemon < ActiveRecord::Base ! validates :nome, :id_nacional, presence: true validates :id_nacional, numericality: { only_integer: true, greater_than: 0 } end
  64. 64. spec/models/pokemon_spec.rb describe 'validações' do ! it { is_expected.to validate_presence_of(:nome) } it { is_expected.to validate_presence_of(:id_nacional) } it { is_expected.to validate_numericality_of(:id_nacional).only_integer .is_greater_than(0) } end
  65. 65. shoulda-matchers os matchers ActiveModel ActiveRecord ActionController
  66. 66. shoulda-matchers além do shoulda-matchers https://github.com/bmabey/email-spec https://github.com/philostler/rspec-sidekiq https://github.com/evansagge/mongoid-rspec
  67. 67. Obrigado!
  68. 68. maurogeorge.com.br

×