SlideShare uma empresa Scribd logo
Desenvolvimento
Baseado em Testes
RSpec - 1.ª parte
Eduardo Mendes
edumendes@gmail.com
@dudumendes




Ferramentas para TDD
@dudumendes




Teste Unitário                   preparar




Ciclo do TDD
                           Componente	
  
               “resetar”    testado	
  de	
            executar

                             maneira	
  
                              isolada



                                 validar
@dudumendes




Ciclo do TDD

  Escreva um teste ANTES
  de escrever um código a ser testado
  Escreva um código que
  apenas faça compilar o teste
  e observe o teste funcionando
  Refatore para o formato mais simples possível
@dudumendes




Teste Unitário                       preparar




Ciclo do TDD

Frameworks xUnit
                               Componente	
  
Baseado em         “resetar”    testado	
  de	
            executar

asserções                        maneira	
  
                                  isolada



                                     validar
@dudumendes




class TestNumeroSimples < Test::Unit::TestCase
	 def test_simples
	 	 assert_equal(4, NumeroSimples.new(2).add(4))
	 	 assert_equal(6, NumeroSimples.new(2).multiply(3))
	 end	
end
@dudumendes




def testeAssertivo
	
	 assertTrue(valores.contains("um")
	 	 	 	 || valores.contains("dois")
	 	 	 	 || valores.contains("tres"))
end
@dudumendes


                                          JUnit in Action


xUnits e DSLs

   começaram a surgir alternativas que possuíam
   mais legibilidade
   utilização de DSLs
     uma tendência das linguagens scripts é
     aproximar a programação da linguagem
     natural, facilitando o entendimento
   contraponto aos xUnits
@dudumendes




Hamcrest                                      JUnit in Action




Framework para declarações
“critérios de correspondência (match)”
Matchers (ex: hasItem, equalTo, anyOf)
  Informam se um determinado objeto casa ou não com algum
  critério

  podem descrever o critério
@dudumendes




No momento RED                          JUnit in Action




 As mensagens de RED bar são mais amigáveis
@dudumendes




Orientação a Objetos




  Orientação a objetos diz mais respeito à
  comunicação entre os objetos do que às
   suas propriedades e comportamentos
@dudumendes




Sistema OO




É um conjunto de objetos que colaboram entre si
@dudumendes




Problemas

Quando se passa a testar a estrutura dos objetos
ao invés do que eles fazem
É preciso pensar nas interações entre
  pessoas e sistemas
  os próprios objetos
É preciso pensar no comportamento
@dudumendes




O Design Emergente

Benefícios do TDD
  Qualidade de código
  Fraco acoplamento
  Alta Coesão
@dudumendes




RSpec
@dudumendes




Instalação



      gem install rspec
@dudumendes




Instalação



        rspec --help
@dudumendes




Instalação



 rspec arquivo/pasta_de_spec
@dudumendes




RSpec

“RSpec is testing tool for the Ruby programming
language

Born under the banner
of Behaviour-Driven Development,

it is designed to make Test-Driven Development a
productive and enjoyable experience.”
                                   Fonte: http://rspec.info/
@dudumendes




RSpec


Criado por Steven Baker, 2005
Na época já existia a ideia e praticantes de TDD
Juntou o que tinha ouvido de BDD com Aslak Hellsoy e
Dave Stels
@dudumendes




RSpec

 describe     it



  expect    should
@dudumendes




describe
É o método utilizado
para agrupar os        describe “titulo” do
testes a serem
executados             end

  os “exemplos”
    testam os
    comportamentos
    dos objetos
@dudumendes




it
 no RSpec, os testes
 são chamados de       it “descrição do comportamento” do
 exemplos              end

 it é o método que
 declara o exemplo
 descreve o
 comportamento do
 exemplo
@dudumendes




expect
método que verifica
um critério, uma     expect(valor_obtido).to valor_esperado
expectativa
@dudumendes




RSpec Hello World
@dudumendes




Regra de Ouro do TDD

   “Nunca codifique uma
    funcionalidade nova


   sem um teste falhando”
@dudumendes

                            ligador_spec.rb
describe Ligador do

 it "deve dizer 'Hello turma!'
     quando receber a mensagem saudar" do

 	ligador = Ligador.new
 	saudacao = ligador.saudar
 	expect(saudacao).to eql "Hello turma!"

 end

end
@dudumendes




rspec ligador_spec.rb
@dudumendes




NameError:
  uninitialized constant Ligador
@dudumendes




class Ligador
	 def saudar
	 	 "Hello turma!"
	 end
end
@dudumendes




rspec ligador_spec.rb
@dudumendes




Ligador
  deve dizer 'Hello turma!'
quando receber a mensagem saudar

Finished in 0.00062 seconds
1 example, 0 failures
@dudumendes




Dicionário RSpec
Subject Code / Sujeito
   Código que possui o comportamento a ser especificado
Expectation / Expectativas
   Expressão que representa o comportamento esperado do Subject Code
Code Example / Exemplo de código
   Exemplo executável de como o Subject Code pod ser utilizado e seu comportamento
   esperado em determinado contexto
Example Group / Grupo de exemplos
   Um grupo de exemplos de código
Spec
   Um arquivo que contém um ou mais grupos de exemplos
@dudumendes




Comparando


Assertions    Expectation
Test method   Code example
Test case     Example Group
@dudumendes




RSpec
Descreve uma conversação



 O RSpec é um DSL capaz de descrever o
 comportamentos dos objetos
   Aproxima as descrições destes comportamentos à
   linguagem natural
   Uma conversação
@dudumendes




Describe
Descreve um objeto

Descreva
  Mas como           Ela “deve iniciar
                      Clientes e servidores
                         devem entender
   cliente e
  “uma                com zero de
                     HTTP e os navegadores
  servidor se
 Conta”
 comunicam?               saldo”
                     devem conhecer HTML
@dudumendes




describe "Uma nova Conta" do
 	

 it "deve iniciar com 0 de saldo" do
 	

 	

 conta = Conta.new
         expect(conta.saldo).to be 0
 	

 end
end
@dudumendes




O método describe
Argumentos
 quantos argumentos forem necessários
 normalmente: 1 ou 2
   descreve o objeto em um estado específico, ou
   um conjunto de comportamentos esperados do
   mesmo
 o 1.º pode ser uma referência a uma classe ou string
 o 2.º, opcional, deve ser uma string
@dudumendes




O método describe
show me the code


 describe “Um Usuario” { ... }
 => Um Usuario
 describe Usuario { ... }
 =>Usuario
 describe Usuario, “sem papeis atribuidos” { ... }
 =>Usuario sem papeis atribuidos
@dudumendes




describe Usuario do
describe “sem papel atribuido” do
	

 it "nao deve acessar conteudo protegido" do
	

 	

 ...

	

 end
end
end
@dudumendes




O método context
alias de describe


  context “sem papel atribuido” { ... }
  =>sem papel atribuido


  torna o código mais legível
  describe -> objetos, comportamentos
  context -> contextos em que objetos deve ser exercitados
@dudumendes




describe Usuario do
 context “sem papel atribuido” do
 	

 it "nao deve acessar conteudo protegido" do
 	

 	

 ...

 	

 end
 end
end
@dudumendes




It
o comportamento que será exercitado

 Descreva
  Mas como                        Ela “deve iniciar
                                   Clientes e servidores
                                      devem entender
   cliente e
   “uma                            com zero de
                                  HTTP e os navegadores
  servidor se
  Conta”
 comunicam?                            saldo”
                                  devem conhecer HTML
@dudumendes




O método it
Argumentos
 uma string e um hash opcional
 string
   uma sentença com o comportamento do código que
   será exercitado
 pode vários em um describe
 se um bloco de código não for passado, o exemplo
 será marcado como pendente
@dudumendes


describe Pilha do
	

 describe "#peek" do
	

 	

 it "deve retornar o elemento do topo" do
	

 	

 	

 pilha = Pilha.new
	

 	

 	

 pilha.push :item
	

 	

 	

 expect(pilha.peek).to be :item
	

 	

 end
	

 	

	

 	

 it "nao deve remover o elemento do topo" do
	

 	

 	

 pilha = Pilha.new
	

 	

 	

 pilha.push :item
	

 	

 	

 expect(pilha.items.length).to be 1
	

 	

 end
	

 end
@dudumendes




rspec spec/pilha_spec.rb --format documentation


    Pilha
     #peek
       deve retornar o elemento do topo
       nao deve remover o elemento do topo
@dudumendes




rspec spec/pilha_spec.rb --format documentation


    Pilha
     #peek
       retorna o elemento do topo
       nao remove o elemento do topo
@dudumendes


describe Pilha do
	

 describe "#peek" do
	

 	

 it "deve retornar o elemento do topo" do
	

 	

 	

 pilha = Pilha.new
	

 	

 	

 pilha.push :item
	

 	

 	

 expect(pilha.peek).to be :item
	

 	

 end
	

 	

	

 	

 it "nao deve remover o elemento do topo" do
	

 	

 	

 pilha = Pilha.new
	

 	

 	

 pilha.push :item
	

 	

 	

 expect(pilha.items.length).to be 1
	

 	

 end
	

 end
@dudumendes




describe Pilha do
	

 pilha = Pilha.new
	

 pilha.push :item

	

 describe "#peek" do
	

 	

 it "deve retornar o elemento do topo" do
	

 	

 	

 expect(pilha.peek).to be :item
	

 	

 end
	

 	

	

 	

 it "nao deve remover o elemento do topo" do
	

 	

 	

 expect(pilha.items.length).to be 1
	

 	

 end
	

 end
end
@dudumendes




Postergando exemplos
@dudumendes




TDD por Kent Beck
            Projeto




   Teste                Teste




           Implementa
@dudumendes




TDD por Kent Beck
                    Projeto



            crie uma lista de teste

         anote e identifique os testes

     seja conciso: uma classe ou método

posteriormente, é possível adicionar mais testes
@dudumendes




Postergando exemplos
“crie uma lista de teste” “anote e identifique os testes”

    O RSpec pode auxiliar a tarefa de identificação de
    “exemplos”
    A sua lista pode ser formada pelos exemplos em um spec
    03 maneiras
      exemplos sem blocos
      exemplos desabilitados por pending
      envolver o código do exemplo com pending, para ser
      notificado quando estiverem FIXED
@dudumendes




Exemplo sem bloco
Contexto
 Você quer criar sua lista de comportamentos a
 serem exercitados
Solução
 Coloque somente a descrição do exemplo para
 montar sua lista
 O RSpec avisará que o exemplo está pendente
@dudumendes




describe TvAberta do
   	

 it "deve ser gratuita" do
   	

 	

 ...
   	

   	

 end
   	

       it "deve possuir os canais abertos" do
           ...
  	

 end
   	

	

 it "nao deve incluir os canais fechados"
end
@dudumendes




TvAberta
 deve ser gratuita
 deve possuir os canais abertos
 nao deve incluir os canais fechados (PENDING: Not yet implemented)
@dudumendes




O método pending
 Contexto
   Você tem um exemplo falhando que ainda não tem como
   passar
   Depende de algo ainda não resolvido
 Solução
   marque o exemplo com o método pending
   o bloco é executado, mas para na linha onde o pending foi
   declarado
   na saída haverá o aviso de pendência
@dudumendes


describe TvAberta do
	

 it "deve ser gratuita" do
	

 	

 ...
	

 end
    it "deve possuir os canais abertos" do
        ...
	

 end
	

 it "nao deve incluir os canais fechados"

    it "deve possuir closed caption" do
	

 	

 pending "esperando correcao de codigo"
	

 	

 TvAberta.closed_caption
	

 end
end
@dudumendes




TvAberta
 deve ser gratuita
 deve possuir os canais abertos
 nao deve incluir os canais fechados (PENDING: Not yet implemented)
 deve possuir closed caption (PENDING: esperando correcao de codigo)

Pending:
 TvAberta nao deve incluir os canais fechados
  # Not yet implemented
  # ./spec/tv_aberta_spec.rb:13
 TvAberta deve possuir closed caption
  # esperando correcao de codigo
  # ./spec/tv_aberta_spec.rb:15
@dudumendes




O método pending
com corpo

   Contexto
      Você tem um exemplo em que um bug foi detectado
      Você gostaria que o código executasse mesmo com a pendência
   Solução
      crie um bloco com pending
      o bloco é executado
         se o erro ocorrer, o RSpec executa como um pending normal
         caso contrário ele avisa que o exemplo está sem problemas (FIXED)
   Após a detecção da correção, é possível livrar o bloco do pending
@dudumendes




describe "um array vazio" do
	

 it "deve ser vazio" do
	

 	

 pending("bug informado 18987") do
	

 	

 	

 expect([]).to be_empty
	

 	

 end
	

 end
end
@dudumendes




um array vazio
 deve ser vazio (FAILED - 1)

Failures:

 1) um array vazio deve ser vazio FIXED
   Expected pending 'bug informado 18987' to fail. No Error was raised.
   # ./spec/array_spec.rb:3:in `block (2 levels) in <top (required)>'
@dudumendes




describe "um array vazio" do
	

 it "deve ser vazio" do
	

 	

	

 	

 	

 expect([]).to be_empty
	

 	

	

 end
end
@dudumendes




Hooks
@dudumendes




04 fases              preparar




                Componente	
  
    “resetar”    testado	
  de	
     executar

                  maneira	
  
                   isolada



                      validar
Hooks
                                   @dudumendes




                 Exemplo




        Before             After
@dudumendes




métodos before / after

métodos before e after
  equivalem às fases de preparar e resetar,
  respectivamente
métodos que executam antes e depois de cada
exemplo
  ou antes e depois de grupo de exemplos
@dudumendes




método before(:each)
exemplo

 Contexto
   alguns exemplos podem exercitar funcionalidades específicas de um
   mesmo objeto
   ao iniciar cada exemplo este objeto deveria se encontrar no mesmo
   estado
 Solução
   coloque o código de configuração em um bloco before(:each)
 Nota
   o padrão do método before é o :each
   pode-se utilizar somente o before
@dudumendes

describe Calculadora do
	

 describe "somar 3 e 4" do
	

 	

 it "deve ser igual a 7" do
	

 	

 	

 calc = Calculadora.new
	

 	

 	

 expect(calc.somar(3,4)).to eql 7
	

 	

 end
	

 end

	

 describe "subtrair 4 - 1" do
	

 	

 it "deve ser igual a 3" do
	

 	

 	

 calc = Calculadora.new
	

 	

 	

 expect(calc.subtrair(4,1)).to eql 3
	

 	

 end
	

 end
end
@dudumendes




describe Calculadora do
	

 before(:each) do
	

 	

 @calc = Calculadora.new
	

 end

	

   describe "somar 3 e 4" do
	

   	

 it "deve ser igual a 7" do
	

   	

 	

 expect(@calc.somar(3,4)).to eql 7
	

   	

 end
	

   end

	

 describe "subtrair 4 - 1" do
	

 	

 it "deve ser igual a 3" do
	

 	

 	

 expect(@calc.subtrair(4,1)).to eql 3
	

 	

 end
	

 end
end
@dudumendes




describe Calculadora do
	

 before do
	

 	

 @calc = Calculadora.new
	

 end

	

   describe "somar 3 e 4" do
	

   	

 it "deve ser igual a 7" do
	

   	

 	

 expect(@calc.somar(3,4)).to eql 7
	

   	

 end
	

   end

	

 describe "subtrair 4 - 1" do
	

 	

 it "deve ser igual a 3" do
	

 	

 	

 expect(@calc.subtrair(4,1)).to eql 3
	

 	

 end
	

 end
end
@dudumendes



método before(:each)



extraia tudo o que for de configuração dos exemplos
para um método before
utilize nestes blocos variáveis de instância
@dudumendes




método before(:all)
Comportamento
  o código englobado por before(:all) executa apenas 01
  vez antes de todos os exemplos do grupo
Cuidado
  componentes devem ser testados de maneira isolada
  estados compartilhados por exemplos podem gerar
  comportamentos inesperados
  não recomendado para variáveis de instância
@dudumendes




métodos after(:each/:all)

after(:each)
   executa após cada exemplo
   normalmente utilizado para restaurar o estado do
   ambiente
after(:all)
   executa após um grupo de exemplos
@dudumendes




	

   before(:each) do
	

   	

 @calc = Calculadora.new
	

   end
	

	

   after(:each) do
	

   	

 @calc = nil
	

   end
@dudumendes




	

 before(:each) do
        puts “executando before”
	

 	

 @calc = Calculadora.new
	

 end
	

	

 after(:each) do
        puts “executando after”
	

 	

 @calc = nil
	

 end
@dudumendes




métodos around(:each)
Contexto
  um código deve ser executado antes e depois de
  cada exemplo
Solução
  utilização de around
Pode falhar, e pode não executar o código
correspondente ao after
@dudumendes




	

 around do |example|
	

 	

 faca_algo_antes
        example.run
        faca_algo_depois
	

 end
@dudumendes




Exceções

throw -> raise
try -> begin
catch -> rescue
finally -> ensure
@dudumendes




	

 around do |example|
       begin
	

 	

 faca_algo_antes
        example.run
       ensure
        faca_algo_depois
       end
	

 end
@dudumendes




Expectations
@dudumendes




Expectations


São a alternativa para as tradicionais asserções
Verificam se o sujeito do exemplo casa com um
comportamento definido na expectativa
@dudumendes




be
     OK se o subject for avaliado como true
             expect(true).to be true
               expect(1).to be 1
              expect(1).to be > 0
              expect(1).to be < 2
              expect(1).to be >= 1
              expect(1).to be <= 2
           expect(true).not_to be true
            expect(1).not_to be > 2
@dudumendes




be_true                                   be_false
         OK se o subject for avaliado como true
expect(true).to be_true
expect(1).to be_true
expect(false).not_to be_true
expect(nil).not_to be_true
         OK se o subject for avaliado como false
                                  expect(false).to be_false
                                     expect(0).to be_false
                              expect(true).not_to be_false
                                expect(nil).not_to be_false
@dudumendes




be_nil

    OK se o subject for avaliado como nil

             expect(nil).to be_nil

          expect(false).not_to be nil
@dudumendes



be_a be_an
be_kind_of be_a_kind_of
OK se a classe do subject for uma subclasse da expectativa


           expect(usuario).to be_a(Objeect)


         expect(usuario).not_to be_a(Pessoa)


         expect(pessoa).not_to be_an(Integer)
@dudumendes




eq, eql, equal, ==, ===
      alo = “alo turma!”                         Logica
 alo.should == “alo turma!”                OK se é o mesmo valor


   expect(alo).to eql(alo)                 OK se é o mesmo valor


  expect(alo).to equal(alo)               OK se é o mesmo objeto

 expect(alo).to_not equal(“alo turma”)   OK se não é o mesmo objeto


     alo.should === alo                   OK se é o mesmo objeto


 alo.should_not === Objec.new            OK se não é o mesmo objeto
@dudumendes




include
OK se o subject inclui todos os elementos da expectativa

             expect([1, 2, 3]).to include(1)
             expect([1, 2, 3]).to include(1,3)
                expect(1..3).to include(1)
            expect(1..3).to include(1, 2, 3)
         expect("alo turma").to include("lo tu")
            expect([1,2,3]).not_to include(4)
        expect("alo turma").not_to include("ali")
@dudumendes




match

OK se o subject casar com a expressão regular da expectativa


            expect("alo turma").match(/alo/)

             expect("alo turma").match(/ali/)
@dudumendes




raise_error
    OK se o bloco lançar a exceção da expectativa

                   expect { raise ArgumentError }.to raise_error


           expect { raise ArgumentError }.to raise_error(ArgumentError)

expect { raise ArgumentError, “nome invalido”}.to raise_error(ArgumentError, "nome
                                    invalido")

expect { raise ArgumentError, “nome invalido”}.to raise_error(ArgumentError, /nome
                                    invalido/)
@dudumendes




Exercício
@dudumendes



Conversão de romanos para
arábicos

Desenvolver em TDD uma funcionalidade que converta
um número romano qualquer em número arábico
O que é importante saber?
@dudumendes




Romanos
 Alguns caracteres possuem valores
I = 1

V = 5

X = 10

L = 50
@dudumendes




Romanos

 Alguns caracteres podem se repetir
 I, X, C, M
 Outros não
 V, L, D
@dudumendes




Romanos

 Algumas combinações de caracteres retornam a
 soma dos elementos
II = 2

II = I + I = 1 + 1 = 2

CCC = 100 + 100 + 100 = 300
@dudumendes




Romanos

 Outras combinações de caracteres retornam a
 subtração dos elementos
IV = 5 - 1 = 4

XL = 50 - 10 = 40

CXLIV = 100 + (50 - 10) + (5 - 1)
@dudumendes




Romanos

 Algumas combinações não são possíveis
IIII

CCCC

XXXX
@dudumendes




Romanos


Entregáveis:

Spec

E a Classe RomanosParser
@dudumendes




Dicas
@dudumendes




Dicas

Exemplos
 devem ser curtos e diretos
 devem testar uma funcionalidade específica
Como testar
 testar um pouco e codificar um pouco
@dudumendes




Dicas
 Exercite o mais simples primeiro
   referências e retornos vazios
   coleções vazias
   casos básicos de recursividade
   valores limites
 utilize tanto quanto possível expect()to be/eql
@dudumendes




Dicas
 Utilize o parâmetro de mensagem
   principalmente quando o teste não é tão claro
 Mantenha os testes pequenos
   coloque somente as expectativas necessárias
   para testar uma funcionalidade
 Mantenha cada teste independente do outro
 Evite puts
@dudumendes




Bibliografia

 ASTELS, David. Test-Driven Development: A Pratical
 Guide. Prentice Hall, 2003.
 CHELIMSKY, David. The RSpec Book. PragBook,
 2011.
 FREEMAN, Steve; PRYCE, Nat. Growing Object-
 Oriented Software, Guiaded by Tests. Addison-Wesley.
 VIEIRA, Fernando. Guia Rápido de RSpec.

Mais conteúdo relacionado

PPTX
Sample - Nabilah's E-portfolio
PDF
RSpec - Testando suas aplicações Ruby on Rails
PDF
Testes In Browser Em Rails Com Capybara E Webdriver
PDF
Como o Cucumber Funciona
PDF
TDD Projeto e Estrategias
PDF
Acesso a banco de dados com JDBC
PDF
Turbinando o desenvolvimento com Eclipse
PDF
Sample - Nabilah's E-portfolio
RSpec - Testando suas aplicações Ruby on Rails
Testes In Browser Em Rails Com Capybara E Webdriver
Como o Cucumber Funciona
TDD Projeto e Estrategias
Acesso a banco de dados com JDBC
Turbinando o desenvolvimento com Eclipse

Destaque (20)

PDF
Introdução à Linguagem Ruby - Fundamentos - Parte 2
PDF
Desenvolvimento web com PHP parte 4
PDF
Html Aula 1 - parte 2
PDF
Java Web 4 - Servlets e JSP 2
PDF
The Power of Collaboration to Build Your Own Startup
PDF
Desenvolvimento Web com PHP parte 7
DOCX
Academia do Arquiteto Globalcode
PDF
Rails - parte 1
PDF
Evolucao de software - parte 2
PDF
RSpec com doubles
PDF
Evolucao de software - parte 1
PDF
Engenharia de Requisitos
PDF
Testes de Software parte 2
PDF
TDD - Prática com RSpec
PDF
Introdução ao TDD
PDF
Desenvolvimento web com PHP parte 3
PDF
AngularJS - Rotas
PDF
Teste de Software - parte 1
PDF
Java Web 2 - Ferramentas e configuração
Introdução à Linguagem Ruby - Fundamentos - Parte 2
Desenvolvimento web com PHP parte 4
Html Aula 1 - parte 2
Java Web 4 - Servlets e JSP 2
The Power of Collaboration to Build Your Own Startup
Desenvolvimento Web com PHP parte 7
Academia do Arquiteto Globalcode
Rails - parte 1
Evolucao de software - parte 2
RSpec com doubles
Evolucao de software - parte 1
Engenharia de Requisitos
Testes de Software parte 2
TDD - Prática com RSpec
Introdução ao TDD
Desenvolvimento web com PHP parte 3
AngularJS - Rotas
Teste de Software - parte 1
Java Web 2 - Ferramentas e configuração
Anúncio

Semelhante a RSpec - Desenvolvimento Baseado em Teste (20)

PDF
Behaviour-Driven Development com Ruby
PDF
BDD com Cucumber
PPT
Dito Tech Talk RSpec
PPTX
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - Grupo Bandeirantes - ...
PPTX
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - .NET SP - Abril-2018
PPTX
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - Hertz - Janeiro-2018
PPTX
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - Developers-SP - Janei...
PDF
BDD em Ação
PPT
BDD: Cucumber + Selenium + Java
PDF
AMD, BDD, e o Javali
PDF
Desenvolvimento orientado a testes
PPTX
TDD (Resumo)
PDF
Padrões para Desenvolvimento de Software Guiado por Testes
PPT
Test-Driven Development - Introdução ao método de construção de software guia...
PDF
Introdução ao TDD
KEY
Bdd e ci
PDF
Introdução ao TDD
PPTX
TDD e BDD - Developers-SP - Abril/2017
PPTX
Behaviour Driven Development
Behaviour-Driven Development com Ruby
BDD com Cucumber
Dito Tech Talk RSpec
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - Grupo Bandeirantes - ...
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - .NET SP - Abril-2018
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - Hertz - Janeiro-2018
Testes na plataforma .NET: TDD, Mocks, BDD e Selenium - Developers-SP - Janei...
BDD em Ação
BDD: Cucumber + Selenium + Java
AMD, BDD, e o Javali
Desenvolvimento orientado a testes
TDD (Resumo)
Padrões para Desenvolvimento de Software Guiado por Testes
Test-Driven Development - Introdução ao método de construção de software guia...
Introdução ao TDD
Bdd e ci
Introdução ao TDD
TDD e BDD - Developers-SP - Abril/2017
Behaviour Driven Development
Anúncio

Mais de Eduardo Mendes (20)

PDF
JavaScript - Introdução com Orientação a Objetos
PDF
Angular JS - Fundamentos
PDF
Singleton - Padrão de Projeto
PDF
Layout Fluido
PDF
Web Design Responsivo
PDF
Html - Aula 4
PDF
Html - Aula 3
PDF
Introdução à Internet, Http e HTML
PDF
PDF
Jquery 2
PDF
Estimativas de Esforço - Engenharia de Software
PDF
Java web 6 JSP Expression Language Taglib parte 2
PDF
Validações no Ruby on Rails
PDF
Padrão Iterator
PDF
Padroes Template-Method (Método Gabarito)
PDF
Padrão Command
PDF
Padrão Fachada
PDF
Padrão Adapter
PDF
Web Design Responsivo
PDF
PHP básico para iniciantes
JavaScript - Introdução com Orientação a Objetos
Angular JS - Fundamentos
Singleton - Padrão de Projeto
Layout Fluido
Web Design Responsivo
Html - Aula 4
Html - Aula 3
Introdução à Internet, Http e HTML
Jquery 2
Estimativas de Esforço - Engenharia de Software
Java web 6 JSP Expression Language Taglib parte 2
Validações no Ruby on Rails
Padrão Iterator
Padroes Template-Method (Método Gabarito)
Padrão Command
Padrão Fachada
Padrão Adapter
Web Design Responsivo
PHP básico para iniciantes

RSpec - Desenvolvimento Baseado em Teste

  • 1. Desenvolvimento Baseado em Testes RSpec - 1.ª parte Eduardo Mendes edumendes@gmail.com
  • 3. @dudumendes Teste Unitário preparar Ciclo do TDD Componente   “resetar” testado  de   executar maneira   isolada validar
  • 4. @dudumendes Ciclo do TDD Escreva um teste ANTES de escrever um código a ser testado Escreva um código que apenas faça compilar o teste e observe o teste funcionando Refatore para o formato mais simples possível
  • 5. @dudumendes Teste Unitário preparar Ciclo do TDD Frameworks xUnit Componente   Baseado em “resetar” testado  de   executar asserções maneira   isolada validar
  • 6. @dudumendes class TestNumeroSimples < Test::Unit::TestCase def test_simples assert_equal(4, NumeroSimples.new(2).add(4)) assert_equal(6, NumeroSimples.new(2).multiply(3)) end end
  • 7. @dudumendes def testeAssertivo assertTrue(valores.contains("um") || valores.contains("dois") || valores.contains("tres")) end
  • 8. @dudumendes JUnit in Action xUnits e DSLs começaram a surgir alternativas que possuíam mais legibilidade utilização de DSLs uma tendência das linguagens scripts é aproximar a programação da linguagem natural, facilitando o entendimento contraponto aos xUnits
  • 9. @dudumendes Hamcrest JUnit in Action Framework para declarações “critérios de correspondência (match)” Matchers (ex: hasItem, equalTo, anyOf) Informam se um determinado objeto casa ou não com algum critério podem descrever o critério
  • 10. @dudumendes No momento RED JUnit in Action As mensagens de RED bar são mais amigáveis
  • 11. @dudumendes Orientação a Objetos Orientação a objetos diz mais respeito à comunicação entre os objetos do que às suas propriedades e comportamentos
  • 12. @dudumendes Sistema OO É um conjunto de objetos que colaboram entre si
  • 13. @dudumendes Problemas Quando se passa a testar a estrutura dos objetos ao invés do que eles fazem É preciso pensar nas interações entre pessoas e sistemas os próprios objetos É preciso pensar no comportamento
  • 14. @dudumendes O Design Emergente Benefícios do TDD Qualidade de código Fraco acoplamento Alta Coesão
  • 16. @dudumendes Instalação gem install rspec
  • 17. @dudumendes Instalação rspec --help
  • 19. @dudumendes RSpec “RSpec is testing tool for the Ruby programming language Born under the banner of Behaviour-Driven Development, it is designed to make Test-Driven Development a productive and enjoyable experience.” Fonte: http://rspec.info/
  • 20. @dudumendes RSpec Criado por Steven Baker, 2005 Na época já existia a ideia e praticantes de TDD Juntou o que tinha ouvido de BDD com Aslak Hellsoy e Dave Stels
  • 21. @dudumendes RSpec describe it expect should
  • 22. @dudumendes describe É o método utilizado para agrupar os describe “titulo” do testes a serem executados end os “exemplos” testam os comportamentos dos objetos
  • 23. @dudumendes it no RSpec, os testes são chamados de it “descrição do comportamento” do exemplos end it é o método que declara o exemplo descreve o comportamento do exemplo
  • 24. @dudumendes expect método que verifica um critério, uma expect(valor_obtido).to valor_esperado expectativa
  • 26. @dudumendes Regra de Ouro do TDD “Nunca codifique uma funcionalidade nova sem um teste falhando”
  • 27. @dudumendes ligador_spec.rb describe Ligador do it "deve dizer 'Hello turma!' quando receber a mensagem saudar" do ligador = Ligador.new saudacao = ligador.saudar expect(saudacao).to eql "Hello turma!" end end
  • 30. @dudumendes class Ligador def saudar "Hello turma!" end end
  • 32. @dudumendes Ligador deve dizer 'Hello turma!' quando receber a mensagem saudar Finished in 0.00062 seconds 1 example, 0 failures
  • 33. @dudumendes Dicionário RSpec Subject Code / Sujeito Código que possui o comportamento a ser especificado Expectation / Expectativas Expressão que representa o comportamento esperado do Subject Code Code Example / Exemplo de código Exemplo executável de como o Subject Code pod ser utilizado e seu comportamento esperado em determinado contexto Example Group / Grupo de exemplos Um grupo de exemplos de código Spec Um arquivo que contém um ou mais grupos de exemplos
  • 34. @dudumendes Comparando Assertions Expectation Test method Code example Test case Example Group
  • 35. @dudumendes RSpec Descreve uma conversação O RSpec é um DSL capaz de descrever o comportamentos dos objetos Aproxima as descrições destes comportamentos à linguagem natural Uma conversação
  • 36. @dudumendes Describe Descreve um objeto Descreva Mas como Ela “deve iniciar Clientes e servidores devem entender cliente e “uma com zero de HTTP e os navegadores servidor se Conta” comunicam? saldo” devem conhecer HTML
  • 37. @dudumendes describe "Uma nova Conta" do it "deve iniciar com 0 de saldo" do conta = Conta.new expect(conta.saldo).to be 0 end end
  • 38. @dudumendes O método describe Argumentos quantos argumentos forem necessários normalmente: 1 ou 2 descreve o objeto em um estado específico, ou um conjunto de comportamentos esperados do mesmo o 1.º pode ser uma referência a uma classe ou string o 2.º, opcional, deve ser uma string
  • 39. @dudumendes O método describe show me the code describe “Um Usuario” { ... } => Um Usuario describe Usuario { ... } =>Usuario describe Usuario, “sem papeis atribuidos” { ... } =>Usuario sem papeis atribuidos
  • 40. @dudumendes describe Usuario do describe “sem papel atribuido” do it "nao deve acessar conteudo protegido" do ... end end end
  • 41. @dudumendes O método context alias de describe context “sem papel atribuido” { ... } =>sem papel atribuido torna o código mais legível describe -> objetos, comportamentos context -> contextos em que objetos deve ser exercitados
  • 42. @dudumendes describe Usuario do context “sem papel atribuido” do it "nao deve acessar conteudo protegido" do ... end end end
  • 43. @dudumendes It o comportamento que será exercitado Descreva Mas como Ela “deve iniciar Clientes e servidores devem entender cliente e “uma com zero de HTTP e os navegadores servidor se Conta” comunicam? saldo” devem conhecer HTML
  • 44. @dudumendes O método it Argumentos uma string e um hash opcional string uma sentença com o comportamento do código que será exercitado pode vários em um describe se um bloco de código não for passado, o exemplo será marcado como pendente
  • 45. @dudumendes describe Pilha do describe "#peek" do it "deve retornar o elemento do topo" do pilha = Pilha.new pilha.push :item expect(pilha.peek).to be :item end it "nao deve remover o elemento do topo" do pilha = Pilha.new pilha.push :item expect(pilha.items.length).to be 1 end end
  • 46. @dudumendes rspec spec/pilha_spec.rb --format documentation Pilha #peek deve retornar o elemento do topo nao deve remover o elemento do topo
  • 47. @dudumendes rspec spec/pilha_spec.rb --format documentation Pilha #peek retorna o elemento do topo nao remove o elemento do topo
  • 48. @dudumendes describe Pilha do describe "#peek" do it "deve retornar o elemento do topo" do pilha = Pilha.new pilha.push :item expect(pilha.peek).to be :item end it "nao deve remover o elemento do topo" do pilha = Pilha.new pilha.push :item expect(pilha.items.length).to be 1 end end
  • 49. @dudumendes describe Pilha do pilha = Pilha.new pilha.push :item describe "#peek" do it "deve retornar o elemento do topo" do expect(pilha.peek).to be :item end it "nao deve remover o elemento do topo" do expect(pilha.items.length).to be 1 end end end
  • 51. @dudumendes TDD por Kent Beck Projeto Teste Teste Implementa
  • 52. @dudumendes TDD por Kent Beck Projeto crie uma lista de teste anote e identifique os testes seja conciso: uma classe ou método posteriormente, é possível adicionar mais testes
  • 53. @dudumendes Postergando exemplos “crie uma lista de teste” “anote e identifique os testes” O RSpec pode auxiliar a tarefa de identificação de “exemplos” A sua lista pode ser formada pelos exemplos em um spec 03 maneiras exemplos sem blocos exemplos desabilitados por pending envolver o código do exemplo com pending, para ser notificado quando estiverem FIXED
  • 54. @dudumendes Exemplo sem bloco Contexto Você quer criar sua lista de comportamentos a serem exercitados Solução Coloque somente a descrição do exemplo para montar sua lista O RSpec avisará que o exemplo está pendente
  • 55. @dudumendes describe TvAberta do it "deve ser gratuita" do ... end it "deve possuir os canais abertos" do ... end it "nao deve incluir os canais fechados" end
  • 56. @dudumendes TvAberta deve ser gratuita deve possuir os canais abertos nao deve incluir os canais fechados (PENDING: Not yet implemented)
  • 57. @dudumendes O método pending Contexto Você tem um exemplo falhando que ainda não tem como passar Depende de algo ainda não resolvido Solução marque o exemplo com o método pending o bloco é executado, mas para na linha onde o pending foi declarado na saída haverá o aviso de pendência
  • 58. @dudumendes describe TvAberta do it "deve ser gratuita" do ... end it "deve possuir os canais abertos" do ... end it "nao deve incluir os canais fechados" it "deve possuir closed caption" do pending "esperando correcao de codigo" TvAberta.closed_caption end end
  • 59. @dudumendes TvAberta deve ser gratuita deve possuir os canais abertos nao deve incluir os canais fechados (PENDING: Not yet implemented) deve possuir closed caption (PENDING: esperando correcao de codigo) Pending: TvAberta nao deve incluir os canais fechados # Not yet implemented # ./spec/tv_aberta_spec.rb:13 TvAberta deve possuir closed caption # esperando correcao de codigo # ./spec/tv_aberta_spec.rb:15
  • 60. @dudumendes O método pending com corpo Contexto Você tem um exemplo em que um bug foi detectado Você gostaria que o código executasse mesmo com a pendência Solução crie um bloco com pending o bloco é executado se o erro ocorrer, o RSpec executa como um pending normal caso contrário ele avisa que o exemplo está sem problemas (FIXED) Após a detecção da correção, é possível livrar o bloco do pending
  • 61. @dudumendes describe "um array vazio" do it "deve ser vazio" do pending("bug informado 18987") do expect([]).to be_empty end end end
  • 62. @dudumendes um array vazio deve ser vazio (FAILED - 1) Failures: 1) um array vazio deve ser vazio FIXED Expected pending 'bug informado 18987' to fail. No Error was raised. # ./spec/array_spec.rb:3:in `block (2 levels) in <top (required)>'
  • 63. @dudumendes describe "um array vazio" do it "deve ser vazio" do expect([]).to be_empty end end
  • 65. @dudumendes 04 fases preparar Componente   “resetar” testado  de   executar maneira   isolada validar
  • 66. Hooks @dudumendes Exemplo Before After
  • 67. @dudumendes métodos before / after métodos before e after equivalem às fases de preparar e resetar, respectivamente métodos que executam antes e depois de cada exemplo ou antes e depois de grupo de exemplos
  • 68. @dudumendes método before(:each) exemplo Contexto alguns exemplos podem exercitar funcionalidades específicas de um mesmo objeto ao iniciar cada exemplo este objeto deveria se encontrar no mesmo estado Solução coloque o código de configuração em um bloco before(:each) Nota o padrão do método before é o :each pode-se utilizar somente o before
  • 69. @dudumendes describe Calculadora do describe "somar 3 e 4" do it "deve ser igual a 7" do calc = Calculadora.new expect(calc.somar(3,4)).to eql 7 end end describe "subtrair 4 - 1" do it "deve ser igual a 3" do calc = Calculadora.new expect(calc.subtrair(4,1)).to eql 3 end end end
  • 70. @dudumendes describe Calculadora do before(:each) do @calc = Calculadora.new end describe "somar 3 e 4" do it "deve ser igual a 7" do expect(@calc.somar(3,4)).to eql 7 end end describe "subtrair 4 - 1" do it "deve ser igual a 3" do expect(@calc.subtrair(4,1)).to eql 3 end end end
  • 71. @dudumendes describe Calculadora do before do @calc = Calculadora.new end describe "somar 3 e 4" do it "deve ser igual a 7" do expect(@calc.somar(3,4)).to eql 7 end end describe "subtrair 4 - 1" do it "deve ser igual a 3" do expect(@calc.subtrair(4,1)).to eql 3 end end end
  • 72. @dudumendes método before(:each) extraia tudo o que for de configuração dos exemplos para um método before utilize nestes blocos variáveis de instância
  • 73. @dudumendes método before(:all) Comportamento o código englobado por before(:all) executa apenas 01 vez antes de todos os exemplos do grupo Cuidado componentes devem ser testados de maneira isolada estados compartilhados por exemplos podem gerar comportamentos inesperados não recomendado para variáveis de instância
  • 74. @dudumendes métodos after(:each/:all) after(:each) executa após cada exemplo normalmente utilizado para restaurar o estado do ambiente after(:all) executa após um grupo de exemplos
  • 75. @dudumendes before(:each) do @calc = Calculadora.new end after(:each) do @calc = nil end
  • 76. @dudumendes before(:each) do puts “executando before” @calc = Calculadora.new end after(:each) do puts “executando after” @calc = nil end
  • 77. @dudumendes métodos around(:each) Contexto um código deve ser executado antes e depois de cada exemplo Solução utilização de around Pode falhar, e pode não executar o código correspondente ao after
  • 78. @dudumendes around do |example| faca_algo_antes example.run faca_algo_depois end
  • 79. @dudumendes Exceções throw -> raise try -> begin catch -> rescue finally -> ensure
  • 80. @dudumendes around do |example| begin faca_algo_antes example.run ensure faca_algo_depois end end
  • 82. @dudumendes Expectations São a alternativa para as tradicionais asserções Verificam se o sujeito do exemplo casa com um comportamento definido na expectativa
  • 83. @dudumendes be OK se o subject for avaliado como true expect(true).to be true expect(1).to be 1 expect(1).to be > 0 expect(1).to be < 2 expect(1).to be >= 1 expect(1).to be <= 2 expect(true).not_to be true expect(1).not_to be > 2
  • 84. @dudumendes be_true be_false OK se o subject for avaliado como true expect(true).to be_true expect(1).to be_true expect(false).not_to be_true expect(nil).not_to be_true OK se o subject for avaliado como false expect(false).to be_false expect(0).to be_false expect(true).not_to be_false expect(nil).not_to be_false
  • 85. @dudumendes be_nil OK se o subject for avaliado como nil expect(nil).to be_nil expect(false).not_to be nil
  • 86. @dudumendes be_a be_an be_kind_of be_a_kind_of OK se a classe do subject for uma subclasse da expectativa expect(usuario).to be_a(Objeect) expect(usuario).not_to be_a(Pessoa) expect(pessoa).not_to be_an(Integer)
  • 87. @dudumendes eq, eql, equal, ==, === alo = “alo turma!” Logica alo.should == “alo turma!” OK se é o mesmo valor expect(alo).to eql(alo) OK se é o mesmo valor expect(alo).to equal(alo) OK se é o mesmo objeto expect(alo).to_not equal(“alo turma”) OK se não é o mesmo objeto alo.should === alo OK se é o mesmo objeto alo.should_not === Objec.new OK se não é o mesmo objeto
  • 88. @dudumendes include OK se o subject inclui todos os elementos da expectativa expect([1, 2, 3]).to include(1) expect([1, 2, 3]).to include(1,3) expect(1..3).to include(1) expect(1..3).to include(1, 2, 3) expect("alo turma").to include("lo tu") expect([1,2,3]).not_to include(4) expect("alo turma").not_to include("ali")
  • 89. @dudumendes match OK se o subject casar com a expressão regular da expectativa expect("alo turma").match(/alo/) expect("alo turma").match(/ali/)
  • 90. @dudumendes raise_error OK se o bloco lançar a exceção da expectativa expect { raise ArgumentError }.to raise_error expect { raise ArgumentError }.to raise_error(ArgumentError) expect { raise ArgumentError, “nome invalido”}.to raise_error(ArgumentError, "nome invalido") expect { raise ArgumentError, “nome invalido”}.to raise_error(ArgumentError, /nome invalido/)
  • 92. @dudumendes Conversão de romanos para arábicos Desenvolver em TDD uma funcionalidade que converta um número romano qualquer em número arábico O que é importante saber?
  • 93. @dudumendes Romanos Alguns caracteres possuem valores I = 1 V = 5 X = 10 L = 50
  • 94. @dudumendes Romanos Alguns caracteres podem se repetir I, X, C, M Outros não V, L, D
  • 95. @dudumendes Romanos Algumas combinações de caracteres retornam a soma dos elementos II = 2 II = I + I = 1 + 1 = 2 CCC = 100 + 100 + 100 = 300
  • 96. @dudumendes Romanos Outras combinações de caracteres retornam a subtração dos elementos IV = 5 - 1 = 4 XL = 50 - 10 = 40 CXLIV = 100 + (50 - 10) + (5 - 1)
  • 97. @dudumendes Romanos Algumas combinações não são possíveis IIII CCCC XXXX
  • 100. @dudumendes Dicas Exemplos devem ser curtos e diretos devem testar uma funcionalidade específica Como testar testar um pouco e codificar um pouco
  • 101. @dudumendes Dicas Exercite o mais simples primeiro referências e retornos vazios coleções vazias casos básicos de recursividade valores limites utilize tanto quanto possível expect()to be/eql
  • 102. @dudumendes Dicas Utilize o parâmetro de mensagem principalmente quando o teste não é tão claro Mantenha os testes pequenos coloque somente as expectativas necessárias para testar uma funcionalidade Mantenha cada teste independente do outro Evite puts
  • 103. @dudumendes Bibliografia ASTELS, David. Test-Driven Development: A Pratical Guide. Prentice Hall, 2003. CHELIMSKY, David. The RSpec Book. PragBook, 2011. FREEMAN, Steve; PRYCE, Nat. Growing Object- Oriented Software, Guiaded by Tests. Addison-Wesley. VIEIRA, Fernando. Guia Rápido de RSpec.

Notas do Editor