SlideShare a Scribd company logo
Mini-Curso
TestesOnRails
 Desenvolvimento Orientado a Testes em Rails
                                               1
2
Disclaimer




             3
http://www.railsrx.com   4
O que testar?
    Quando testar?
     Quanto testar?
Quantos asserts por teste?
    Teste quebrado
     mudar teste ou código?

                              5
Contextualização

Testes, Testes Automatizados, Desenvolvimento
     Orientado a Testes, Design Evolutivo,
              Ferramentas de Teste

            TestesOnRails

Unit, Functionals, Integration,View,View Helpers,
          Routes, Performance, Mocks

 Shoulda, RSpec, RSpec-Rails, faker, Cucumber,
                   Koujou
                                                    6
Em
teoria...
            7
Testes
Desenvolver   Testar
Desenvolver   Testar
?
?
$?


?
$
cr
  iaç
          ão

de
     sc
       ob
            er
               ta
co
     rr
       eç
           ão
X
Testes
Automáticos
Programa
Teste



        Programa
Teste



        Programa
Teste



        Programa
(...)
public void meuTeste() {
  int par1 = 1;
  int par2 = 1;
  int result = Classe.soma(par1,par1);
  assertEquals(2, result);
}
(...)




                                (...)
                                public int soma(int a, int b) {
                                  // código
                                }
                                (...)
(...)
public void meuTeste() {
  int par1 = 1;
                                            Preparação
  int par2 = 1;
  int result = Classe.soma(par1,par1);
  assertEquals(2, result);
}
(...)




                                (...)
                                public int soma(int a, int b) {
                                  // código
                                }
                                (...)
(...)
public void meuTeste() {
  int par1 = 1;
  int par2 = 1;
  int result = Classe.soma(par1,par2);
  assertEquals(2, result);
                                              Exercício
}
(...)




                                (...)
                                public int soma(int a, int b) {
                                  // código
                                }
                                (...)
(...)
public void meuTeste() {
  int par1 = 1;
  int par2 = 1;
  int result = Classe.soma(par1,par1);

}
  assertEquals(2, result);
                                             Verificação
(...)




                                (...)
                                public int soma(int a, int b) {
                                  // código
                                }
                                (...)
vale a pena   ?
X
X
X
10




30
10   20




30   30
10   20   30




30   30   30
10   20   30   40




30   30   30   30
10   20   30   40   50




30   30   30   30   30
10   20   30   40   50   60




30   30   30   30   30   30
10   20   30   40   50   60   70




30   30   30   30   30   30   30
public class Romanos {

public static String parse(int entrada) {

        StringBuilder resultado = new StringBuilder();
        if (entrada <= 3) {
          for (int i = 0; i < entrada; i++)
            resultado.append("I");
          return resultado.toString();
        }

        else if (entrada == 4) {
          return "IV";
        } else if(entrada == 5){
          return "V";
        } else if (entrada < 9){
          resultado.append("V");
          return resultado.toString();
        }else if (entrada == 9){
          return "IX";
        }else{
          return "X";
        }
    }


}
public static String parse(int entrada) {

         public static String parse(int entrada) {                  else if (entrada == 4) {
                                                                      return "IV";
                                                                                                              public static String parse(int entrada) {
             else if (entrada == 4) {                               } else if(entrada == 5){
               return "IV";                                           return "V";
                                                                                                                      else if (entrada == 4) {
             } else if(entrada == 5){                               }
                                                                                                                        return "IV";
               return "V";                                                                                            } else if(entrada == 5){
             }                                                  }
                                                                                                                        return "V";
                                                                                                                      }
         }
                                                                                                              }




                                                     public class Romanos {

                                                     public static String parse(int entrada) {

                                                             StringBuilder resultado = new StringBuilder();
public static String parse(int entrada) {                    if (entrada <= 3) {
                                                               for (int i = 0; i < entrada; i++)                  public static String parse(int entrada) {
        else if (entrada == 4) {                                 resultado.append("I");
          return "IV";                                         return resultado.toString();                              else if (entrada == 4) {
        } else if(entrada == 5){                             }                                                             return "IV";
          return "V";                                                                                                    } else if(entrada == 5){
        }                                                    else if (entrada == 4) {                                      return "V";
                                                               return "IV";                                              }
}                                                            } else if(entrada == 5){
                                                               return "V";                                        }
                                                             } else if (entrada < 9){
                                                               resultado.append("V");
                                                               return resultado.toString();
                                                             }else if (entrada == 9){
                                                               return "IX";
                                                             }else{
                                                               return "X";
                                                             }
                                                         }


                                                     }
    public static String parse(int entrada) {                                                                     public static String parse(int entrada) {
         else if (entrada == 4) {                                                                                       else if (entrada == 4) {
           return "IV";                                                                                                   return "IV";
         } else if(entrada == 5){                                                                                       } else if(entrada == 5){
           return "V";                                                                                                    return "V";
         }                                                                                                              }
    }                                                                                                             }
                                                               public static String parse(int entrada) {

                                                                    else if (entrada == 4) {
                                                                      return "IV";
                                                                    } else if(entrada == 5){
                                                                      return "V";
                                                                    }

                                                               }
public static String parse(int entrada) {

         public static String parse(int entrada) {                  else if (entrada == 4) {
                                                                      return "IV";
                                                                                                              public static String parse(int entrada) {
             else if (entrada == 4) {                               } else if(entrada == 5){
               return "IV";                                           return "V";
                                                                                                                      else if (entrada == 4) {
             } else if(entrada == 5){                               }
                                                                                                                        return "IV";
               return "V";                                                                                            } else if(entrada == 5){
             }                                                  }
                                                                                                                        return "V";
                                                                                                                      }
         }
                                                                                                              }




                                                     public class Romanos {

                                                     public static String parse(int entrada) {

                                                             StringBuilder resultado = new StringBuilder();
public static String parse(int entrada) {                    if (entrada <= 3) {
                                                               for (int i = 0; i < entrada; i++)                  public static String parse(int entrada) {
        else if (entrada == 4) {                                 resultado.append("I");
          return "IV";                                         return resultado.toString();                              else if (entrada == 4) {
        } else if(entrada == 5){                             }                                                             return "IV";
          return "V";                                                                                                    } else if(entrada == 5){
        }                                                    else if (entrada == 4) {                                      return "V";
                                                               return "IV";                                              }
}                                                            } else if(entrada == 5){
                                                               return "V";                                        }
                                                             } else if (entrada < 9){
                                                               resultado.append("V");
                                                               return resultado.toString();
                                                             }else if (entrada == 9){
                                                               return "IX";
                                                             }else{
                                                               return "X";
                                                             }
                                                         }


                                                     }
    public static String parse(int entrada) {                                                                     public static String parse(int entrada) {
         else if (entrada == 4) {                                                                                       else if (entrada == 4) {
           return "IV";                                                                                                   return "IV";
         } else if(entrada == 5){                                                                                       } else if(entrada == 5){
           return "V";                                                                                                    return "V";
         }                                                                                                              }
    }                                                                                                             }
                                                               public static String parse(int entrada) {

                                                                    else if (entrada == 4) {
                                                                      return "IV";
                                                                    } else if(entrada == 5){
                                                                      return "V";
                                                                    }

                                                               }
public static String parse(int entrada) {

         public static String parse(int entrada) {                  else if (entrada == 4) {
                                                                      return "IV";
                                                                                                              public static String parse(int entrada) {
             else if (entrada == 4) {                               } else if(entrada == 5){
               return "IV";                                           return "V";
                                                                                                                      else if (entrada == 4) {
             } else if(entrada == 5){                               }
                                                                                                                        return "IV";
               return "V";                                                                                            } else if(entrada == 5){
             }                                                  }
                                                                                                                        return "V";
                                                                                                                      }
         }
                                                                                                              }




                                                     public class Romanos {

                                                     public static String parse(int entrada) {

                                                             StringBuilder resultado = new StringBuilder();
public static String parse(int entrada) {                    if (entrada <= 3) {
                                                               for (int i = 0; i < entrada; i++)                  public static String parse(int entrada) {
        else if (entrada == 4) {                                 resultado.append("I");
          return "IV";                                         return resultado.toString();                              else if (entrada == 4) {
        } else if(entrada == 5){                             }                                                             return "IV";
          return "V";                                                                                                    } else if(entrada == 5){
        }                                                    else if (entrada == 4) {                                      return "V";
                                                               return "IV";                                              }
}                                                            } else if(entrada == 5){
                                                               return "V";                                        }
                                                             } else if (entrada < 9){
                                                               resultado.append("V");
                                                               return resultado.toString();
                                                             }else if (entrada == 9){
                                                               return "IX";
                                                             }else{
                                                               return "X";
                                                             }
                                                         }


                                                     }
    public static String parse(int entrada) {                                                                     public static String parse(int entrada) {
         else if (entrada == 4) {                                                                                       else if (entrada == 4) {
           return "IV";                                                                                                   return "IV";
         } else if(entrada == 5){                                                                                       } else if(entrada == 5){
           return "V";                                                                                                    return "V";
         }                                                                                                              }
    }                                                                                                             }
                                                               public static String parse(int entrada) {

                                                                    else if (entrada == 4) {
                                                                      return "IV";
                                                                    } else if(entrada == 5){
                                                                      return "V";
                                                                    }

                                                               }
evolvability
maintainability

       mantenabilidade
       manutenibilidade
       manutenabilidade

 capacidade de manutenção
Custo




        Tempo
Custo




        Tempo
Test
 Driven
Development
GREEN
RED


        teste


GREEN
RED

código           teste


         GREEN
RED

código           teste


         GREEN

                         refactoring
RED




GREEN
RED
        Plan




GREEN
RED
             Plan


Do
     GREEN
RED
               Plan


Do
     GREEN

       Check
RED
               Plan


Do                    Act
     GREEN

       Check
Design Evolutivo
?
RED




GREEN
Foco

       RED




       GREEN
Foco
Ritmo
        RED




        GREEN
Foco
 Ritmo
             RED
Disciplina




             GREEN
Foco
  Ritmo
               RED
 Disciplina
Simplicidade



               GREEN
Ferramentas
   (Java)
Unidade
Bancos de
 Dados
Aceitação
Aplicações WEB




Selenium
Performance (WEB)
Testes

       Testes Automáticos

Desenvolvimento Orientado a Testes

        Design Evolutivo

          Ferramentas            46
47
http://www.railsrx.com   48
Quando se fala de
testes, fala-se de...
                   Mudanças
Corretude
             Direcionamento
 Robustez
            Design evolutivo
    Documentação               49
O que testar?
       caminho feliz

   caminhos alternativos

erros conhecidos e esperados
                               50
51
TestesOnRails




                52
53
Kiwitter
           54
$ rails kiwitter
    create
    create app/controllers
    create app/helpers
    create app/models
    create app/views/layouts
    create config/environments
    create config/initializers
    create config/locales
    (...)
    create log/server.log
    create log/production.log
    create log/development.log
    create log/test.log
                                 55
kiwitter $ script/generate scaffold user 
                                    login:string 
                                    email:string 
                                    password:string
    exists app/models/
    exists app/controllers/
    exists app/helpers/
    create app/views/users
    exists app/views/layouts/
    (...)
    create test/unit/user_test.rb
    create test/fixtures/users.yml
    create db/migrate
    create db/migrate/20090729120900_create_users.rb
                                                       56
kiwitter $ script/server
=> Booting WEBrick
=> Rails 2.3.3 application starting on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2009-07-29 09:29:22] INFO WEBrick 1.3.1
[2009-07-29 09:29:22] INFO ruby 1.8.7 (2009-06-12) [powerpc-darwin9]
[2009-07-29 09:29:22] INFO WEBrick::HTTPServer#start: pid=54915 port=3000
                                                                       57
kiwitter $ rake db:migrate
(in ...maredeagilidade_ceara/labs/rails_test/kiwitter)
== CreateUsers: migrating ========================================
-- create_table(:users)
   -> 0.0082s
== CreateUsers: migrated (0.0094s) =================================




                                                                       58
Unit
  Functional
 Integration
Performance

Tests
               59
kiwitter $ rake -T
rake test
rake test:benchmark
rake test:functionals
rake test:integration
rake test:plugins
rake test:profile
rake test:recent
rake test:uncommitted
rake test:units         60
kiwitter $ rake test:units

Started
........FE
Finished in 1.181401 seconds.


                                61
........FE
 1) Failure:
test_should_sign_in_only_when_vali
d_credentials_are_given(UserTest) [/
test/unit/user_test.rb:25]:
<nil> is not true.

                                       62
........FE
 2) Error:
test_should_display_user_greetings(
UsersHelperTest):
ArgumentError: wrong number of
arguments (1 for 0)

                                      63
Rails
       environments




test   development   production   64
65
Fixtures



           66
Test fixture refers to the fixed
                    state used as a baseline for
                 running tests in software testing.
                The purpose of a test fixture is to
                ensure that there is a well known
                  and fixed environment in which
                  tests are run so that results are
                repeatable. Some people call this
                          the test context.



http://en.wikipedia.org/wiki/Test_fixture         67
68
http://ar.rubyonrails.org/classes/Fixtures.html   69
Inicialização da base
     database.yml


  Identificação dos
 arquivos de testes
      test/**/*.rb


  Para cada teste
   identificação dos
   métodos de testes
                        70
Para cada método de teste
       test “should xxx yyy”


            1. carrega fixtures
                   test/fixtures/users.yml
            2. executa setup
            3. executa o teste
                           .....FE
            4. executa teardown
            5. “descarrega” fixtures
                     rollback ou delete     71
ios
                 ár
          n   it
       s U
  s t e
Te



                         72
Test::Unit::TestCase
ActiveSupport::TestCase +
Rails Unit Tests

                            73
Rails Unit Tests

 1. fixtures
 2. setup
 3. test/unit/*_test.rb
 4. teardown
                          74
Test::Unit::TestCase
assert
                     assert_not_same
assert_block
                     assert_nothing_raised
assert_equal
                     assert_nothing_thrown
assert_in_delta
                     assert_operator
assert_instance_of
                     assert_raise
assert_kind_of
                     assert_raises
assert_match
                     assert_respond_to
assert_nil
                     assert_same
assert_no_match
                     assert_send
assert_not_equal
                     assert_throws
assert_not_nil
                                             75
http://ruby-doc.org/stdlib/   76
http://api.rubyonrails.org/   77
assert                  assert_nothing_thrown
assert_block            assert_operator
assert_equal            assert_raise
assert_in_delta         assert_raises
assert_instance_of      assert_respond_to
assert_kind_of          assert_same
assert_match            assert_send
assert_nil              assert_throws
assert_no_match         build_message
assert_not_equal        flunk
assert_not_nil          use_pp=
assert_not_same         assert_difference
assert_nothing_raised   assert_no_difference
                                                78
Kiwitter

           79
Kiwitter

           80
81
kiwitter $ rake test:units
...
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/
1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/
unit/helpers/users_helper_test.rb" "test/unit/
user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader
Started
.
Finished in 0.201504 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
                                                         82
83
kiwitter $ rake test:units
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader.rb" "test/unit/helpers/users_helper_test.rb" "test/
unit/user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader
Started
.F
Finished in 0.378072 seconds.

 1) Failure:
test_should_require_login(UserTest) [/test/unit/user_test.rb:16]:
<nil> is not true.

2 tests, 2 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)                                     84
85
kiwitter $ rake test:units
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/
gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader.rb" "test/unit/helpers/
users_helper_test.rb" "test/unit/user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/
rake-0.8.7/lib/rake/rake_test_loader
Started
..
Finished in 0.178493 seconds.

2 tests, 2 assertions, 0 failures, 0 errors
                                                         86
Labs
Desenvolver Orientado a Testes


Validação de obrigatoriedade de senha e email
        Validação de unicidade do login
          Validação formato do email




                                                87
88
89
kiwitter $ rake test:units
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader.rb" "test/unit/helpers/users_helper_test.rb" "test/unit/user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
..E
Finished in 0.322179 seconds.

  1) Error:
test_should_sign_in_only_when_valid_credentials_are_given(UserTest):
NoMethodError: undefined method `signin' for #<Class:0x1a761f0>
   /test/unit/user_test.rb:22:in
`test_should_sign_in_only_when_valid_credentials_are_given'

3 tests, 2 assertions, 0 failures, 1 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)
                                                                                      90
1) Error:
test_should_sign_in_only_when_valid_credentials_are_given(UserTest):
ArgumentError: wrong number of arguments (2 for 0)
   /test/unit/user_test.rb:22:in `signin'
   /test/unit/user_test.rb:22:in
`test_should_sign_in_only_when_valid_credentials_are_given'

3 tests, 2 assertions, 0 failures, 1 errors                            91
1) Failure:
test_should_sign_in_only_when_valid_credentials_are_given(UserTest)
[/test/unit/user_test.rb:22]:
<nil> is not true.

3 tests, 3 assertions, 1 failures, 0 errors
                                                                      92
1) Failure:
test_should_sign_in_only_when_valid_credentials_are_given(UserTest)
[/test/unit/user_test.rb:23]:
<false> is not true.

3 tests, 4 assertions, 1 failures, 0 errors
                                                                 93
Quem
espera
 false?
          94
1) Failure:
test_should_sign_in_only_when_valid_credentials_are_given(UserT
est) [/test/unit/user_test.rb:22]:
<nil> is not true.

3 tests, 3 assertions, 1 failures, 0 errors
 1) Failure:
test_should_sign_in_only_when_valid_credentials_are_given(UserT
est) [/test/unit/user_test.rb:23]:
<false> is not true.

3 tests, 4 assertions, 1 failures, 0 errors

      Problema quando se tem vários
       asserts num mesmo test case.                           95
Refactoring




              96
kiwitter $ rake test:units
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader.rb" "test/unit/helpers/users_helper_test.rb" "test/unit/user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
.FF..
Finished in 0.421486 seconds.

 1) Failure:
test_should_not_sign_in_when_invalid_password_is_given(UserTest) [/test/unit/
user_test.rb:27]:
<false> is not true.

 2) Failure:
test_should_not_sign_in_when_invalid_username_is_given(UserTest) [/test/unit/
user_test.rb:31]:
<false> is not true.

5 tests, 5 assertions, 2 failures, 0 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)                                              97
1) Failure:
test_should_sign_in_only_when_valid_credentials_are_given(U
serTest) [/test/unit/user_test.rb:23]:
<nil> is not true.

5 tests, 5 assertions, 1 failures, 0 errors
                                                              98
Fixtures
mecanismo para criação de massa de dados de testes




                                                 99
100
101
kiwitter $ rake test:units
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/
gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/unit/
helpers/users_helper_test.rb" "test/unit/user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader
Started
.....
Finished in 0.367962 seconds.

5 tests, 5 assertions, 0 failures, 0 errors

                                                              102
Labs

  Testes unitários como TDD para
criação (post) de mensagens (update)
           por um usuário
                                       103
Testes Funcionais   104
HTTP Req



    ?



           105
Test::Unit::TestCase
ActiveSupport::TestCase    +
ActiveController::TestCase +
Rails Functional Tests

                           106
ActiveController::TestCase
Métodos   Mock Objects     “Hashes”

get       @controller      session
post      @request         cookies
put       @response        flash
delete                     assigns
xhr
          @response.body   session[:user_id]
                                               107
ActiveController::TestCase

assert_dom_equal       assert_select
assert_dom_not_equal   assert_select_email
assert_valid           assert_select_encoded
assert_redirected_to   assert_select_rjs
assert_response        css_select
assert_template        response_from_page_or_rjs
assert_generates       unescape_rjs
assert_recognizes      assert_no_tag
assert_routing         assert_tag

                                              108
1. setup
params = {:project_id => @project.id.to_s, :task_id => @task.id.to_s}
session = {:user_id => 12345}


  2. teste
<método http> <método do controller> <params> <session> <flash>

    get                  :index
   post                 :create               params session
   put                  :update        {:notice => “Task updated”}
  delete                    ...
                                                                   109
Não testa rotas!

*Sempre* enviar parâmetros
    HTTP como string

                             110
st atus
assert_ response

‘c onteúdo’
  assert_t emplate

        ionam ento
redirec       t
     asser t_redirec



                       111
assert_response 200
assert_response 404
assert_response :success
assert_response :missing
assert_template “index”
assert_template “users/new”
assert_redirect_to :controller => task, :id => 3
assert_redirect_to new_task_url
assert_redirect_to @task
                                                   112
Unit Tests


Functional Tests   113
Kiwitter




           114
Kiwitter

       115
kiwitter $ rake test:functionals
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/
rake/rake_test_loader.rb" "test/functional/users_controller_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader
Started
F......
Finished in 0.618077 seconds.

 1) Failure:
test_should_create_user(UsersControllerTest) [/test/functional/
users_controller_test.rb:16]:
"User.count" didn't change by 1.
<3> expected but was
<2>.

7 tests, 9 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)                                         116
117
kiwitter $ rake test:functionals
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/
gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/
functional/users_controller_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader
Started
.......
Finished in 0.883527 seconds.

7 tests, 10 assertions, 0 failures, 0 errors

                                                              118
119
kiwitter $ script/generate controller sessions new
    exists app/controllers/
    exists app/helpers/
    create app/views/sessions
    exists test/functional/
    exists test/unit/helpers/
    create app/controllers/sessions_controller.rb
    create test/functional/sessions_controller_test.rb
    create app/helpers/sessions_helper.rb
    create test/unit/helpers/sessions_helper_test.rb
    create app/views/sessions/new.html.erb

                                                         120
121
122
kiwitter $ rake test:functionals
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/functional/
users_controller_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
F.......
Finished in 0.842942 seconds.

 1) Failure:
test_should_authenticate_user(SessionsControllerTest) [/test/functional/
sessions_controller_test.rb:8]:
<nil> expected to not be nil.                  assert_not_nil
8 tests, 12 assertions, 1 failures, 0 errors       assigns(:user)
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)
                                                                                       123
124
kiwitter $ rake test:functionals
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb"
"test/functional/users_controller_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader
Started
F.......
Finished in 0.57468 seconds.                      assert_template
                                                 "users/home"
 1) Failure:
test_should_authenticate_user(SessionsControllerTest) [/test/functional/
sessions_controller_test.rb:13]:
expecting <"users/home"> but rendering with <"sessions/create.html.erb">

8 tests, 13 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)                                 125
126
kiwitter $ rake test:functionals
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/
rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/
functional/users_controller_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader
Started
F.......
                                                       inconsistência
Finished in 0.610806 seconds.

 1) Failure:
test_should_authenticate_user(SessionsControllerTest) [/test/functional/
sessions_controller_test.rb:9]:
Expected response to be a <:success>, but was <302>

8 tests, 11 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)
                                                                                  127
128
kiwitter $ rake test:functionals
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/
rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/
functional/users_controller_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader
Started                                 redirect não implica na
F.......                              renderização da página de
Finished in 0.99891 seconds.                      destino
 1) Failure:
test_should_authenticate_user(SessionsControllerTest) [/test/functional/
sessions_controller_test.rb:13]:
expecting <"users/home"> but rendering with <"">

8 tests, 13 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)
                                                                                      129
130
kiwitter alegomes$ rake test:functionals
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/
gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/
functional/sessions_controller_test.rb" "test/functional/
users_controller_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader
Started
........
Finished in 0.547148 seconds.

8 tests, 12 assertions, 0 failures, 0 errors

                                                             131
Labs
 Testar/implementar autenticação
        de usuário inválido
            @user não deve ser criada
usuário deve ser redirecionado para página de login

          Testar/implementar
          post de mensagem

                                                      132
Testes de Integração




                       133
Req Controller 1


Req Controller 2


Req Controller 3




        ?
                   134
Testes de Integração


Testes de Aceitação
                   135
Integração
desenvolvedores


                X
   linguagem ruby
                    Aceitação
                      clientes
                     linguagem natural




                                         136
TD
não participa do ciclo de




                            137
{post, get, delete...}_via_redirect
             segue todos os redirects

         follow_redirect!
            segue apenas um redirect

                redirect?
        verifica se a última req foi redirect

                   https!
     faz com que todas as reqs pareçam HTTPs

                    host!
             altera o servidor da app
                                               138
139
kiwitter $ script/generate integration_test post_updates
    exists test/integration/
    create test/integration/post_updates_test.rb




                                                       140
141
kiwitter $ rake test:integration
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/
gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/
integration/post_updates_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader
Started
.
Finished in 0.255598 seconds.

1 tests, 2 assertions, 0 failures, 0 errors

                                                              142
Lab?   143
Testes da View




                 144
assert_select
                145
Tradeoff



           146
assert_select("form")
       verifica a existência da tag <form>

<span>Maré de Agilidade</span>
    assert_select("span", "Maré de Agilidade")
        assert_select("span", /Agilidade/)



                                                 147
148
149
150
kiwitter $ rake test:integration
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/
gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/
integration/post_updates_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/
lib/rake/rake_test_loader
Started
.
Finished in 0.943481 seconds.

1 tests, 3 assertions, 0 failures, 0 errors

                                                              151
1) Failure:
test_should_post_an_update(PostUpdatesTest) [/test/
integration/post_updates_test.rb:15]:
Expected at least 1 element matching
"div#welcome_messageeeeeeeee", found 0.
<false> is not true.

1 tests, 3 assertions, 1 failures, 0 errors



                                                      152
Testes dos View Helpers




                          153
154
155
156
kiwitter $ rake test:units
/opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/
rake_test_loader.rb" "test/unit/helpers/sessions_helper_test.rb" "test/unit/helpers/
updates_helper_test.rb" "test/unit/helpers/users_helper_test.rb" "test/unit/
update_test.rb" "test/unit/user_test.rb"
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
.......E
Finished in 0.510089 seconds.

 1) Error:
test_should_display_user_greetings(UsersHelperTest):
NoMethodError: undefined method `display_greetings' for #<UsersHelperTest:
0x1ba7e84>
   /test/unit/helpers/users_helper_test.rb:10:in `test_should_display_user_greetings'

8 tests, 8 assertions, 0 failures, 1 errors
rake aborted!
Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...]

(See full trace by running task with --trace)
                                                                                           157
8 tests, 9 assertions, 0 failures, 0 errors
                                              158
Bom
senso

        159
Testes de Rotas




                  160
ActionController::Assertions::RoutingAssertions



assert_generates
assert_generates "/items", :controller => "items", :action => "index"


assert_recognizes
assert_recognizes {:controller => 'items', :action => 'create'},
                  {:path => 'items', :method => :post}


assert_routing
assert_routing '/home', :controller => 'home', :action => 'index'




     http://api.rubyonrails.org/classes/ActionController/Assertions/RoutingAssertions.html   161
Labs
    View
View Helper
   Routes
              162
Mock
Objects

      163
Quem não tem cão...   164
...caça com gato.   165
Objeto real indisponível ou de difícil acesso.

   Reprodução de cenários complexos.




                                                 166
Mocks Aren't Stubs
The term 'Mock Objects' has become a popular one to
describe special case objects that mimic real objects for
testing. Most language environments now have frameworks
that make it easy to create mock objects. What's often not
realized, however, is that mock objects are but one form of
special case test object, one that enables a different style of
testing. In this article I'll explain how mock objects work,
how they encourage testing based on behavior verification,
and how the community around them uses them to develop
a different style of testing.

         http://www.martinfowler.com/articles/mocksArentStubs.html   167
Stu
      168
Objeto falso que retorna um valor predeterminado
          para uma chamada de método

objeto.stubs(:metodo).and_returns("alguma coisa")

 “ignore a implementacao real de objeto.metodo e
              retorne ‘alguma coisa’”

            se objeto.metodo for invocado
                retornará "alguma coisa"

          se objeto.metodo NÃO for invocado
                    nada acontecerá
                                               169
170
17 tests, 28 assertions, 0 failures, 0 errors
                                                171
17 tests, 26 assertions, 1 failures, 0 errors
                                                172
Moc
  173
semelhante ao stub,
            com uma diferença
objeto.stubs(:metodo).adn_returns("alguma coisa")

           se objeto.metodo for invocado
               retornará "alguma coisa"

         se objeto.metodo NÃO for invocado
                    o teste falhará

                                               174
1) Failure:
test_mock_example(UserTest) [/test/unit/user_test.rb:35]:
not all expectations were satisfied
unsatisfied expectations:
- expected exactly once, not yet invoked: #<Mock:0x1884090>.email(any_parameters)
satisfied expectations:
- expected exactly once, already invoked once: #<Mock:0x1884090>.login(any_parameters)

9 tests, 12 assertions, 1 failures, 0 errors
rake aborted!

                                                                                    175
9 tests, 13 assertions, 0 failures, 0 errors




                                               176
mocks      returns
            raises
        any_instance
              with
         pattern matches
                       177
User.any_instance.expects(:login).returns(nil)




  user.login deve ser executado
     apenas uma única vez

                                             178
user.expects(:login).once
user.expects(:login).twice
user.expects(:login).at_least_once
user.expects(:login).at_most_once
user.expects(:login).at_least(3)
user.expects(:login).at_most(3)
user.expects(:login).times(5)
user.expects(:login).times(4..6)
user.expects(:login).never
                                 179
http://flexmock.rubyforge.org
   http://mocha.rubyforge.org
http://double-ruby.rubyforge.org
         http://rspec.info


                                   180
Labs
Stubs e Mocks




                181
http://thoughtbot.com/projects/shoulda   182
context
  setup do
    @u = ....
  end

  should “alguma coisa” do
    assert....
  end
end
                             183
$ sudo gem install thoughtbot-shoulda --source=http://gems.github.com
Password:
Successfully installed thoughtbot-shoulda-2.10.2
1 gem installed
Installing ri documentation for thoughtbot-shoulda-2.10.2...
Installing RDoc documentation for thoughtbot-shoulda-2.10.2...



                http://wiki.github.com/thoughtbot/shoulda/installation   184
require ‘shoulda‘


                185
http://dev.thoughtbot.com/shoulda/   186
assert_accepts
assert_contains
assert_does_not_contain
assert_rejects
assert_same_elements

   http://dev.thoughtbot.com/shoulda/classes/Shoulda/Assertions.html   187
assert_bad_value
assert_good_value
assert_save
assert_valid


http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActiveRecord/Assertions.html   188
assert_did_not_send_email
assert_sent_email



 http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActionMailer/Assertions.html   189
190
should_change                                    should_render_without_layout
should_not_change                                should_respond_with
should_assign_to                                 should_respond_with_content_type
should_filter_params                              should_return_from_session
should_not_assign_to                             should_route
should_not_set_the_flash                          should_set_session
should_redirect_to                               should_set_the_flash_to
should_render_template                           should_render_a_form
should_render_with_layout                        should_render_page_with_metadata




                 http://dev.thoughtbot.com/shoulda/classes/Shoulda/Macros.html
       http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActionController/Macros.html
          http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActionView/Macros.html      191
should_allow_mass_assignment_of
                                                              should_have_named_scope
should_allow_values_for
                                                              should_have_one
should_belong_to
                                                              should_have_readonly_attributes
should_ensure_length_at_least
                                                              should_not_allow_mass_assignment_of
should_ensure_length_in_range
                                                              should_not_allow_values_for
should_ensure_length_is
                                                              should_only_allow_numeric_values_for
should_ensure_value_in_range
                                                              should_protect_attributes
should_have_and_belong_to_many
                                                              should_require_acceptance_of
should_have_class_methods
                                                              should_require_attributes
should_have_db_column
                                                              should_require_unique_attributes
should_have_db_columns
                                                              should_validate_acceptance_of
should_have_index
                                                              should_validate_numericality_of
should_have_indices
                                                              should_validate_presence_of
should_have_instance_methods
                                                              should_validate_uniqueness_of
should_have_many




           http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActiveRecord/Macros.html         192
Lab



  193
194




“    RSpec is
  the original
   Behaviour
           Driven
Development
framework for
       Ruby.

   http://rspec.info
Test Driven *

     corretude            qualidade



< 100%      = 100%



 rebola     a ordem não
no mato       importa
                                      195
testes
           passado
   descrição de algo pronto




     X
especificação
            futuro
  descrição de algo inexistente
                                  196
$ sudo gem install rspec
Password:
**************************************************

 Thank you for installing rspec-1.2.8

 Please be sure to read History.rdoc and Upgrade.rdoc
 for useful information about this release.

**************************************************
Successfully installed rspec-1.2.8
1 gem installed
Installing ri documentation for rspec-1.2.8...
Installing RDoc documentation for rspec-1.2.8...
(...)
                                                        197
kiwitter_rspec $ script/generate rspec
    exists lib/tasks
    create lib/tasks/rspec.rake
    create script/autospec
    create script/spec
    create script/spec_server
    exists spec
    create spec/rcov.opts
    create spec/spec.opts
    create spec/spec_helper.rb
                                     198
kiwitter_rspec $ rake -T
rake spec                   rake spec:plugin_doc
rake spec:clobber_rcov      rake spec:plugins
rake spec:controllers       rake spec:plugins:rspec_on_rails
rake spec:db:fixtures:load   rake spec:rcov
rake spec:doc               rake spec:server:restart
rake spec:helpers           rake spec:server:start
rake spec:integration       rake spec:server:status
rake spec:lib               rake spec:server:stop
rake spec:models            rake spec:views


                                                          199
describe funcionalidade
  it “should do A” do
   ...
   end
   it “should do B” do
      actual.should expected
   end
 ...
end
                               200
201
202
should_not                          should have_at_most
should be_true
                               be_instance_of                      have_exactly
should be_false
                               should_not                          helper
should be_nil
                               be_an_instance_of                   should include
should
                               should be_close                     should_not include
be_[arbitrary_predicate]
                               should_not be_close                 inspect_object
should_not be_nil
                               be_instance_of                      should match
should_not
                               be_kind_of                          should_not match
be_[arbitrary_predicate]
                               should change                       should raise_error
be_a
                               should_not change                   should_not raise_error
should be_kind_of
                               should eql                          should respond_to
should be_a_kind_of
                               should_not eql                      should_not respond_to
should_not be_kind_of
                               should equal                        should satisfy
should_not
                               should_not equal                    should_not satisfy
be_a_kind_of
                               should exist                        simple_matcher
be_an
                               should_not exist                    should throw_symbol
should be_instance_of
                               should have                         should_not
should
                               should_not have                     throw_symbol
be_an_instance_of
                               should have_at_least                wrap_expectation

             http://rspec.rubyforge.org/rspec/1.2.8/classes/Spec/Matchers.html         203
expected.XXXXX?
expected.should be_XXXXX
expected.should be_a_XXXXX
expected.should be_an_XXXXX
expected.should have_key(:k)
expected.has_key?(:k)
expected.should have(10).items
expected.should have(10).laranjas
expected.should have(10).filhos
                                    204
205
206
$ sudo gem install     rspec-rails
Password:
**************************************************

 Thank you for installing rspec-rails-1.2.7.1

 If you are upgrading, do this in each of your rails apps
 that you want to upgrade:

  $ ruby script/generate rspec

 Please be sure to read History.rdoc and Upgrade.rdoc
 for useful information about this release.

**************************************************
Successfully installed rspec-rails-1.2.7.1
1 gem installed
Installing ri documentation for rspec-rails-1.2.7.1...
Installing RDoc documentation for rspec-rails-1.2.7.1...
(...)                                                       207
$ rails kiwitter_rspec
    create
    create app/controllers
    create app/helpers
    create app/models
    create app/views/layouts
    create config/environments
    create config/initializers
    create config/locales
    create db
    create doc
    (...)
                                208
kiwitter_rspec $ script/generate rspec_scaffold user login:string
                                                  password:string
                                                  email:string
    (...)
    create spec/controllers/
    create spec/routing/
    create spec/models/
    create spec/helpers/
    create spec/fixtures/
    create spec/views/users
    create spec/integration/
    (...)
    create spec/views/users/new.html.erb_spec.rb
    create spec/views/users/show.html.erb_spec.rb
    create spec/integration/users_spec.rb
    create db/migrate
    create db/migrate/20090802144903_create_users.rb
     route map.resources :users
                                                                209
script/generate rspec_scaffold update
       user:references message:text



script/generate migration update_user_join


                                             210
Mais testes
gerados que o
  tradicional
 Test::Unit
                211
alta especialização
                      212
Model Spec




             213
Controller Spec




              214
Controller Spec



    response.should
response.should_not
                      {   be_success
                          be_redirect
                          redirect_to(url ou hash)
                          render_template(‘users/home’)




                                                     215
View Spec




            216
View Spec


Test::Unit             RSpec
assigns(@user)        assigns[:user]
 session[:user_id]    session[:user_id]
cookies[“user_id”]   cookies[“user_id”]
   flash[:notice]        flash[:notice]
                                       217
View Spec



                                                    {
                                                                 be_valid
                                                                 have_rjs
                    response.should                              have_tag
                response.should_not                              have_text
                                                                 have_text
                                                                 send_email

response.should have_tag “xxx” do
                                ...
                              end                     {          with_encoded
                                                                 with_tag
                                                                 without_tag

      http://rspec.rubyforge.org/rspec-rails/1.2.7.1/classes/Spec/Rails/Matchers.html   218
Routing Spec




...




                 219
Helper Spec




              220
{
       spec
       spec:controllers
       spec:helpers
       spec:integration
rake   spec:lib
       spec:models
       spec:plugins
       spec:views
                          221
kiwitter_rspec $ rake spec:models
..

Finished in 1.703168 seconds

2 examples, 0 failures

                                222
Lab

      223
faker
 Faker (...) is used to easily
    generate fake data


         http://faker.rubyforge.org   224
kiwitter $ sudo gem install faker
Password:
Successfully installed faker-0.3.1
1 gem installed
Installing ri documentation for faker-0.3.1...
Installing RDoc documentation for faker-0.3.1...


                                               225
require ‘faker‘


                  226
Maida McDermott
April Metz
Rowena Jakubowski
Anita Lueilwitz
Alena Ferry
                    227
puts Faker::Internet.email
mia_schmidt@quigleycrist.ca
nicolette@king.uk
isaac@schmitt.info
cade_buckridge@spinkajaskolski.com
laurine@klein.name


puts Faker::Address.zip_code
11695
72143
21715-9288
15719-7873
90548-7155
                                     228
puts Faker::Lorem.paragraphs(2)
Rerum quos hic et. Autem harum ea asperiores consequatur libero et. Ipsum cumque dicta optio
voluptate. Et quia officia minus iure vitae. Ducimus delectus unde neque odio voluptas
inventore minima.
Fugiat nihil error incidunt nihil quo natus omnis. Quis consequatur aut totam ad. Doloribus
nihil officiis nobis rerum tempora. Nam eos mollitia delectus assumenda veritatis.

Itaque voluptatem repudiandae odit provident error ut. Perspiciatis est facilis sit quis et
qui vel. Hic corrupti recusandae aliquid possimus.
Et error ad ut voluptatem non labore. Accusantium non tempore aut assumenda architecto enim.
Quasi eos et dicta. Tempore quia optio eos pariatur fugiat.

Est neque molestias aliquid et. Dolor cum nemo tempora. Eum ratione esse quam magni officiis
dolor. Earum maxime sit eaque optio laboriosam tempora voluptatibus.
Quo illum ipsa sit. Ea sequi id et sunt nemo quibusdam maxime. Ab voluptate nesciunt maxime
rerum iure explicabo in. Sed quidem dignissimos est officia necessitatibus sed qui. Similique
odit qui id nostrum corporis autem quas enim.

Sunt placeat eum architecto tempora non. Est libero aut repellat mollitia. Quisquam non quia
et id est repellat qui aspernatur.
Animi ut sit quaerat. Dignissimos enim esse autem qui sed aut optio a. Debitis facilis aut
eaque alias exercitationem quia impedit. Maiores vitae id odio est inventore.

Aut accusamus et et vel sint. Quo ducimus dolor nemo quia libero autem. Assumenda est voluptas
debitis in libero.
Illo sit deleniti tenetur nisi. Reiciendis et odit fugiat velit hic. Quo nisi deserunt sit.
                                                                                          229
http://faker.rubyforge.org/rdoc
Array
rand shuffle
Faker::Address
city city_prefix city_suffix secondary_address street_address
street_name street_suffix uk_country uk_county uk_postcode us_state
us_state_abbr zip_code
Faker::Company
bs catch_phrase name suffix
Faker::Internet
domain_name domain_suffix domain_word email free_email user_name
Faker::Lorem
paragraph paragraphs sentence sentences words
Faker::Name
first_name last_name name prefix suffix
Faker::PhoneNumber
phone_number                                                     230
http://cukes.info   231
232
DSL

Rails Test

Rails Code   233
DSL         features
             scenarios




Rails Test     steps




Rails Code               233
$ sudo gem install cucumber
Password:
Successfully installed term-ansicolor-1.0.4
Successfully installed polyglot-0.2.6
Successfully installed treetop-1.3.0
Successfully installed diff-lcs-1.1.2
Successfully installed builder-2.1.2
Successfully installed cucumber-0.3.92
6 gems installed
Installing ri documentation for term-ansicolor-1.0.4...
Installing ri documentation for polyglot-0.2.6...
Installing ri documentation for treetop-1.3.0...
(...)
Installing RDoc documentation for diff-lcs-1.1.2...
Installing RDoc documentation for builder-2.1.2...
Installing RDoc documentation for cucumber-0.3.92...
                                                          234
kiwitter $ script/plugin install git://github.com/brynary/webrat.git
Initialized empty Git repository in .../kiwitter/vendor/plugins/webrat/.git/
remote: Counting objects: 275, done.
remote: Compressing objects: 100% (236/236), done.
remote: Total 275 (delta 36), reused 170 (delta 20)
Receiving objects: 100% (275/275), 5.07 MiB | 154 KiB/s, done.
Resolving deltas: 100% (36/36), done.
From git://github.com/brynary/webrat
 * branch         HEAD        -> FETCH_HEAD
= Webrat - Ruby Acceptance Testing for Web applications
...
== Description

Webrat lets you quickly write expressive and robust acceptance tests for a Ruby
web application.



                                                                            235
kiwitter $ sudo gem install nokogiri
Building native extensions. This could take a while...
Successfully installed nokogiri-1.3.3
1 gem installed
Installing ri documentation for nokogiri-1.3.3...
Installing RDoc documentation for nokogiri-1.3.3...



                                                         236
kiwitter $ script/generate cucumber
    create features/step_definitions
    create features/step_definitions/webrat_steps.rb
    create config/environments/cucumber.rb
    create features/support
    create features/support/env.rb
    create features/support/paths.rb
    exists lib/tasks
    create lib/tasks/cucumber.rake
    create script/cucumber

                                                      237
Feature: caso de uso/estória em teste
 In order objetivo da funcionalidade
 Stakeholder
 o que o stakeholder deseja

 Background
  Given pré-condições
  And mais pré-condições
    | login    | email              | password |
    | alegomes | alegomes@gmail.com | ale123   |
    | luciana | lu@brasilia.net     | xuxu     |


  Scenario: cenário/fluxo em teste
    Given pré-condições
    When ação do usuário
    Then resultado da ação do usuário              238
kiwitter $ script/generate feature users_and_updates
   exists features/step_definitions
   create features/manage_users_and_updates.feature
   create features/step_definitions/users_and_updates_steps.rb




                                                           239
DSL

Rails Test

Rails Code   240
Teste de
 aceitação
gerado pelo
 Cucumber



              241
modificado para o kiwitter   242
kiwitter $ rake features
/opt/local/bin/ruby -I "/opt/local/lib/ruby/gems/1.8/gems/cucumber-0.3.92/lib:lib" "/opt/local/lib/
ruby/gems/1.8/gems/cucumber-0.3.92/bin/cucumber" --format pretty features/
manage_users_and_updates.feature
Feature: Post update messages
  In order to make my life widely public
  As a User
  I want to post short messages describing what I am doing

  Scenario: Post new messages                         # features/manage_users_and_updates.feature:6
    Given I am at users home page                     # features/manage_users_and_updates.feature:7
    And I have entered a text message up to 140 chars # features/manage_users_and_updates.feature:8
    When I press post                                 # features/manage_users_and_updates.feature:9
    Then the message should be registered             # features/manage_users_and_updates.feature:10

1 scenario (1 undefined)
4 steps (4 undefined)
0m0.653s

...




                                                                                                243
...

You can implement step definitions for undefined steps with these
snippets:

Given /^I am at users home page$/ do
  pending
end

Given /^I have entered a text message up to 140 chars$/ do
  pending
end

When /^I press post$/ do
  pending
end

Then /^the message should be registered$/ do
  pending
end


                                                               244
DSL

Rails Test

Rails Code   245
Feature steps
gerados pelo

script/generate
    feature


                246
...

You can implement step definitions for undefined steps with
these snippets:

Given /^I am at users home page$/ do
  pending
end

Given /^I have entered a text message up to 140 chars$/ do
  pending
end

When /^I press post$/ do
  pending
end

Then /^the message should be registered$/ do
  pending
end
                                                              247
kiwitter $ rake features
/opt/local/bin/ruby -I "/opt/local/lib/ruby/gems/1.8/gems/cucumber-0.3.92/lib:lib" "/opt/
local/lib/ruby/gems/1.8/gems/cucumber-0.3.92/bin/cucumber" --format pretty features/
manage_users_and_updates.feature
Feature: Post update messages
  In order to make my life widely public
 As a User
  I want to post short messages describing what I am doing

 Scenario: Post new messages
  Given I am at users home page
   TODO (Cucumber::Pending)
   features/manage_users_and_updates.feature:7:in `Given I am at users home page'
  And I have entered a text message up to 140 chars
  When I press post
  Then the message should be registered

1 scenario (1 pending)
4 steps (3 skipped, 1 pending)
0m0.134s
                                                                                       248
Given I am at users home page
   TODO (Cucumber::Pending)
    features/manage_users_and_updates.feature:7:in `Given I am at users home page'




  Given /^I am at users home page$/ do
    visit "users/home"
  end




                                                                                     249
kiwitter $ rake features
...
Scenario: Post new messages
users_controller.home
    Given I am at users home page
    And I have entered a text message up to 140 chars
     TODO (Cucumber::Pending)
     features/manage_users_and_updates.feature:8:in `And I
have entered a text message up to 140 chars'
    When I press post
    Then the message should be registered

1 scenario (1 pending)
4 steps (2 skipped, 1 pending, 1 passed)
0m0.260s                                                 250
And I have entered a text message up to 140 chars
    TODO (Cucumber::Pending)
    features/manage_users_and_updates.feature:8:in `And I have entered a
text message up to 140 chars'




                                                                           251
kiwitter $ cucumber features/manage_users_and_updates.feature
Feature: Post update messages
 In order to make my life widely public
 As a User
 I want to post short messages describing what I am doing

 Scenario: Post new messages
users_controller.home
  Given I am at users home page
   And I have entered a text message up to 140 chars
  When I press post
   TODO (Cucumber::Pending)
    features/manage_users_and_updates.feature:9:in `When I press post'
  Then the message should be registered

1 scenario (1 pending)
4 steps (1 skipped, 1 pending, 2 passed)
0m0.305s
                                                                         252
When I press post
  TODO (Cucumber::Pending)
  features/manage_users_and_updates.feature:9:in `When I press post'




                                                                       253
kiwitter $ cucumber features/manage_users_and_updates.feature
Feature: Post update messages
 In order to make my life widely public
 As a User
 I want to post short messages describing what I am doing

 Scenario: Post new messages
users_controller.home
  Given I am at users home page
  And I have entered a text message up to 140 chars
  When I press post
  Then the message should be registered
   TODO (Cucumber::Pending)
    features/manage_users_and_updates.feature:10:in `Then the
message should be registered'

1 scenario (1 pending)
4 steps (1 pending, 3 passed)
0m0.282s                                                        254
Then the message should be registered
   TODO (Cucumber::Pending)
   features/manage_users_and_updates.feature:10:in `Then the message should be registered'




                                         ?
                                                                                             255
webrat




    http://github.com/brynary/webrat/tree/master   256
kiwitter $ script/plugin install git://github.com/brynary/webrat.git
Initialized empty Git repository in .../kiwitter/vendor/plugins/webrat/.git/
remote: Counting objects: 275, done.
remote: Compressing objects: 100% (236/236), done.
remote: Total 275 (delta 36), reused 170 (delta 20)
Receiving objects: 100% (275/275), 5.07 MiB | 125 KiB/s, done.
Resolving deltas: 100% (36/36), done.
From git://github.com/brynary/webrat
 * branch         HEAD        -> FETCH_HEAD
(= Webrat - Ruby Acceptance Testing for Web applications

- http://gitrdoc.com/brynary/webrat
- http://groups.google.com/group/webrat
- http://webrat.lighthouseapp.com/
- http://github.com/brynary/webrat
- #webrat on Freenode
(...)

                                                                          257
http://www.zenspider.com/ZSS/Products/ZenTest/   258
http://www.michaelleung.us/koujou   259
http://eigenclass.org/hiki/rcov   260
$ sudo gem install rcov
Password:
Building native extensions. This could take a while...
Successfully installed rcov-0.8.1.2.0
1 gem installed
Installing ri documentation for rcov-0.8.1.2.0...
Installing RDoc documentation for rcov-0.8.1.2.0...



                                                         261
$ rcov --version
rcov 0.8.1.2 2007-11-22


                          262
kiwitter $ ./script/plugin install --force http://svn.codahale.com/rails_rcov
+ ./MIT-LICENSE
+ ./README
+ ./tasks/rails_rcov.rake




                    http://agilewebdevelopment.com/plugins/rails_rcov      263
kiwitter $ rake -T | grep rcov
rake doc:plugins:rails_rcov
                                     rake test:profile:clobber_rcov
rake spec:clobber_rcov
                                     rake test:profile:rcov
rake spec:rcov
                                     rake test:recent:clobber_rcov
rake test:benchmark:clobber_rcov
                                     rake test:recent:rcov
rake test:benchmark:rcov
                                     rake test:test:clobber_rcov
rake test:functionals:clobber_rcov
                                     rake test:test:rcov
rake test:functionals:rcov
                                     rake test:uncommitted:clobber_rcov
rake test:integration:clobber_rcov
                                     rake test:uncommitted:rcov
rake test:integration:rcov
                                     rake test:units:clobber_rcov
rake test:plugins:clobber_rcov
                                     rake test:units:rcov
rake test:plugins:rcov



                                                                     264
kiwitter $ rake test:units:rcov
                 10 tests, 13 assertions, 1 failures, 1 errors
+----------------------------------------------------+-------+-------+--------+
|                   File                             | Lines | LOC | COV       |
+----------------------------------------------------+-------+-------+--------+
|.../ruby/1.8/gems/sqlite3-ruby-1.2.5/lib/sqlite3.rb |     1 |     1 | 100.0% |
|...gems/sqlite3-ruby-1.2.5/lib/sqlite3/constants.rb |    49 |    44 | 97.7% |
|.../gems/sqlite3-ruby-1.2.5/lib/sqlite3/database.rb |   721 |   340 | 40.3% |
|...3-ruby-1.2.5/lib/sqlite3/driver/native/driver.rb |   219 |   180 | 48.3% |
|....8/gems/sqlite3-ruby-1.2.5/lib/sqlite3/errors.rb |    68 |    58 | 84.5% |
|...8/gems/sqlite3-ruby-1.2.5/lib/sqlite3/pragmas.rb |   271 |   190 | 45.8% |
|...gems/sqlite3-ruby-1.2.5/lib/sqlite3/resultset.rb |   180 |   114 | 72.8% |
|...gems/sqlite3-ruby-1.2.5/lib/sqlite3/statement.rb |   231 |   128 | 50.0% |
|...ems/sqlite3-ruby-1.2.5/lib/sqlite3/translator.rb |   109 |    64 | 20.3% |
|...1.8/gems/sqlite3-ruby-1.2.5/lib/sqlite3/value.rb |    57 |    44 | 29.5% |
|app/controllers/application_controller.rb           |    48 |    21 | 23.8% |
|app/controllers/sessions_controller.rb              |    32 |     9 | 22.2% |
|app/controllers/updates_controller.rb               |    85 |    60 | 13.3% |
|app/controllers/users_controller.rb                 |    89 |    63 | 14.3% |
|app/helpers/application_helper.rb                   |     3 |     2 | 100.0% |
|app/helpers/sessions_helper.rb                      |     3 |     2 | 100.0% |
|app/helpers/updates_helper.rb                       |     2 |     2 | 100.0% |
|app/helpers/users_helper.rb                         |     8 |     5 | 40.0% |
|app/models/update.rb                                |     5 |     4 | 100.0% |
|app/models/user.rb                                  |     8 |     6 | 100.0% |
+----------------------------------------------------+-------+-------+--------+
|Total                                               | 2189 | 1337 | 46.3% |
                                                                              265
+----------------------------------------------------+-------+-------+--------+
266
Q&A

More Related Content

What's hot

Fnt software solutions placement paper
Fnt software solutions placement paperFnt software solutions placement paper
Fnt software solutions placement paperfntsofttech
 
E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9
Ismar Silveira
 
Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014
Raimon Ràfols
 
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDKEric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
GuardSquare
 
ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...
ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...
ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...
Istanbul Tech Talks
 
SoCal Code Camp 2015: An introduction to Java 8
SoCal Code Camp 2015: An introduction to Java 8SoCal Code Camp 2015: An introduction to Java 8
SoCal Code Camp 2015: An introduction to Java 8
Chaitanya Ganoo
 
Pas oct12
Pas oct12Pas oct12
Eric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protectionEric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protection
GuardSquare
 
김재석, C++ 프로그래머를 위한 C#, NDC2011
김재석, C++ 프로그래머를 위한 C#, NDC2011김재석, C++ 프로그래머를 위한 C#, NDC2011
김재석, C++ 프로그래머를 위한 C#, NDC2011devCAT Studio, NEXON
 
Verilog 語法教學
Verilog 語法教學 Verilog 語法教學
Verilog 語法教學
艾鍗科技
 
2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine
2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine
2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine
Frankie Dintino
 
Simulado java se 7 programmer
Simulado java se 7 programmerSimulado java se 7 programmer
Simulado java se 7 programmer
Miguel Vilaca
 
Renaming Tokens
Renaming TokensRenaming Tokens
Renaming Tokens
yanamm
 
Virtual Separation of Concerns (2011 Update)
Virtual Separation of Concerns (2011 Update)Virtual Separation of Concerns (2011 Update)
Virtual Separation of Concerns (2011 Update)
chk49
 
Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >
Sergey Platonov
 

What's hot (20)

Fnt software solutions placement paper
Fnt software solutions placement paperFnt software solutions placement paper
Fnt software solutions placement paper
 
E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9E:\Plp 2009 2\Plp 9
E:\Plp 2009 2\Plp 9
 
Appsec obfuscator reloaded
Appsec obfuscator reloadedAppsec obfuscator reloaded
Appsec obfuscator reloaded
 
Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014Improving Android Performance at Droidcon UK 2014
Improving Android Performance at Droidcon UK 2014
 
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDKEric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
Eric Lafortune - ProGuard: Optimizer and obfuscator in the Android SDK
 
ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...
ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...
ITT 2014 - Eric Lafortune - ProGuard, Optimizer and Obfuscator in the Android...
 
7
77
7
 
SoCal Code Camp 2015: An introduction to Java 8
SoCal Code Camp 2015: An introduction to Java 8SoCal Code Camp 2015: An introduction to Java 8
SoCal Code Camp 2015: An introduction to Java 8
 
Pas oct12
Pas oct12Pas oct12
Pas oct12
 
PAS 2012
PAS 2012PAS 2012
PAS 2012
 
Eric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protectionEric Lafortune - ProGuard and DexGuard for optimization and protection
Eric Lafortune - ProGuard and DexGuard for optimization and protection
 
김재석, C++ 프로그래머를 위한 C#, NDC2011
김재석, C++ 프로그래머를 위한 C#, NDC2011김재석, C++ 프로그래머를 위한 C#, NDC2011
김재석, C++ 프로그래머를 위한 C#, NDC2011
 
Verilog 語法教學
Verilog 語法教學 Verilog 語法教學
Verilog 語法教學
 
2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine
2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine
2 + 2 = 5: Monkey-patching CPython with ctypes to conform to Party doctrine
 
Simulado java se 7 programmer
Simulado java se 7 programmerSimulado java se 7 programmer
Simulado java se 7 programmer
 
Test Engine
Test EngineTest Engine
Test Engine
 
Renaming Tokens
Renaming TokensRenaming Tokens
Renaming Tokens
 
Virtual Separation of Concerns (2011 Update)
Virtual Separation of Concerns (2011 Update)Virtual Separation of Concerns (2011 Update)
Virtual Separation of Concerns (2011 Update)
 
Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >Антон Бикинеев, Writing good std::future&lt; C++ >
Антон Бикинеев, Writing good std::future&lt; C++ >
 
Math test
Math testMath test
Math test
 

Similar to Minicurso de TestesOnRails

Kotlin decompiled
Kotlin decompiledKotlin decompiled
Kotlin decompiled
Ruslan Klymenko
 
20070329 Java Programing Tips
20070329 Java Programing Tips20070329 Java Programing Tips
20070329 Java Programing TipsShingo Furuyama
 
OrderTest.javapublic class OrderTest {       Get an arra.pdf
OrderTest.javapublic class OrderTest {         Get an arra.pdfOrderTest.javapublic class OrderTest {         Get an arra.pdf
OrderTest.javapublic class OrderTest {       Get an arra.pdf
akkhan101
 
Better Software: introduction to good code
Better Software: introduction to good codeBetter Software: introduction to good code
Better Software: introduction to good codeGiordano Scalzo
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
Benjamin Waye
 
TDD Hands-on
TDD Hands-onTDD Hands-on
TDD Hands-on
Shuji Watanabe
 
Modify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdf
Modify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdfModify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdf
Modify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdf
arjuncorner565
 
Turbinando o compilador do Java 8
Turbinando o compilador do Java 8Turbinando o compilador do Java 8
Turbinando o compilador do Java 8
Marcelo de Castro
 
Java Class Design
Java Class DesignJava Class Design
Java Class Design
Ganesh Samarthyam
 
Function & Recursion in C
Function & Recursion in CFunction & Recursion in C
Function & Recursion in C
Aditya Nihal Kumar Singh
 
Kotlin killed Java stars
Kotlin killed Java starsKotlin killed Java stars
Kotlin killed Java stars
Matteo Bonifazi
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
iMasters
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
BTI360
 
Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7
Paulo Morgado
 
Please use Java to solve the following So.pdf
Please use Java to solve the following So.pdfPlease use Java to solve the following So.pdf
Please use Java to solve the following So.pdf
cronkwurphyb44502
 
Javaoneconcurrencygotchas 090610192215 Phpapp02
Javaoneconcurrencygotchas 090610192215 Phpapp02Javaoneconcurrencygotchas 090610192215 Phpapp02
Javaoneconcurrencygotchas 090610192215 Phpapp02Tarun Kumar
 
Apache PIG - User Defined Functions
Apache PIG - User Defined FunctionsApache PIG - User Defined Functions
Apache PIG - User Defined Functions
Christoph Bauer
 
import java.util.Scanner;public class Factorial { method usi.pdf
import java.util.Scanner;public class Factorial { method usi.pdfimport java.util.Scanner;public class Factorial { method usi.pdf
import java.util.Scanner;public class Factorial { method usi.pdf
aptind
 

Similar to Minicurso de TestesOnRails (20)

Kotlin decompiled
Kotlin decompiledKotlin decompiled
Kotlin decompiled
 
20070329 Java Programing Tips
20070329 Java Programing Tips20070329 Java Programing Tips
20070329 Java Programing Tips
 
OrderTest.javapublic class OrderTest {       Get an arra.pdf
OrderTest.javapublic class OrderTest {         Get an arra.pdfOrderTest.javapublic class OrderTest {         Get an arra.pdf
OrderTest.javapublic class OrderTest {       Get an arra.pdf
 
Better Software: introduction to good code
Better Software: introduction to good codeBetter Software: introduction to good code
Better Software: introduction to good code
 
Benefits of Kotlin
Benefits of KotlinBenefits of Kotlin
Benefits of Kotlin
 
TDD Hands-on
TDD Hands-onTDD Hands-on
TDD Hands-on
 
Modify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdf
Modify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdfModify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdf
Modify HuffmanTree.java and HuffmanNode.java to allow the user to se.pdf
 
Turbinando o compilador do Java 8
Turbinando o compilador do Java 8Turbinando o compilador do Java 8
Turbinando o compilador do Java 8
 
Java Class Design
Java Class DesignJava Class Design
Java Class Design
 
Function & Recursion in C
Function & Recursion in CFunction & Recursion in C
Function & Recursion in C
 
Kotlin killed Java stars
Kotlin killed Java starsKotlin killed Java stars
Kotlin killed Java stars
 
Kotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan SoaresKotlin : Advanced Tricks - Ubiratan Soares
Kotlin : Advanced Tricks - Ubiratan Soares
 
Scala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 WorldScala vs Java 8 in a Java 8 World
Scala vs Java 8 in a Java 8 World
 
FSE 2008
FSE 2008FSE 2008
FSE 2008
 
Comp102 lec 7
Comp102   lec 7Comp102   lec 7
Comp102 lec 7
 
Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7Tuga IT 2017 - What's new in C# 7
Tuga IT 2017 - What's new in C# 7
 
Please use Java to solve the following So.pdf
Please use Java to solve the following So.pdfPlease use Java to solve the following So.pdf
Please use Java to solve the following So.pdf
 
Javaoneconcurrencygotchas 090610192215 Phpapp02
Javaoneconcurrencygotchas 090610192215 Phpapp02Javaoneconcurrencygotchas 090610192215 Phpapp02
Javaoneconcurrencygotchas 090610192215 Phpapp02
 
Apache PIG - User Defined Functions
Apache PIG - User Defined FunctionsApache PIG - User Defined Functions
Apache PIG - User Defined Functions
 
import java.util.Scanner;public class Factorial { method usi.pdf
import java.util.Scanner;public class Factorial { method usi.pdfimport java.util.Scanner;public class Factorial { method usi.pdf
import java.util.Scanner;public class Factorial { method usi.pdf
 

More from SEA Tecnologia

Loomio how to Series - Working on a Discussion
Loomio how to Series - Working on a DiscussionLoomio how to Series - Working on a Discussion
Loomio how to Series - Working on a Discussion
SEA Tecnologia
 
Loomio how to Series - Creating a new Group of People
Loomio how to Series - Creating a new Group of PeopleLoomio how to Series - Creating a new Group of People
Loomio how to Series - Creating a new Group of People
SEA Tecnologia
 
Loomio how to Series - Creating a new Discussion
Loomio how to Series - Creating a new DiscussionLoomio how to Series - Creating a new Discussion
Loomio how to Series - Creating a new Discussion
SEA Tecnologia
 
Gerentes em Crise existencial - Existimos no Universo Ágil?
Gerentes em Crise existencial - Existimos no Universo Ágil?Gerentes em Crise existencial - Existimos no Universo Ágil?
Gerentes em Crise existencial - Existimos no Universo Ágil?
SEA Tecnologia
 
O curioso caso de Náutilus Button
O curioso caso de Náutilus ButtonO curioso caso de Náutilus Button
O curioso caso de Náutilus Button
SEA Tecnologia
 
Contratos de desenvolvimento de software para governo blue pill or red pill?
Contratos de desenvolvimento de software para governo  blue pill or red pill?Contratos de desenvolvimento de software para governo  blue pill or red pill?
Contratos de desenvolvimento de software para governo blue pill or red pill?
SEA Tecnologia
 
#Fail
#Fail#Fail
Agilidade no Governo
Agilidade no GovernoAgilidade no Governo
Agilidade no Governo
SEA Tecnologia
 
Os benefícios e desafios da participação pública digital
Os benefícios e desafios da participação pública digitalOs benefícios e desafios da participação pública digital
Os benefícios e desafios da participação pública digital
SEA Tecnologia
 
A escola do século XXI deve ser ágil, enxuta e empreendedora.
A escola do século XXI deve ser ágil, enxuta e empreendedora.A escola do século XXI deve ser ágil, enxuta e empreendedora.
A escola do século XXI deve ser ágil, enxuta e empreendedora.SEA Tecnologia
 
Lean Startup
Lean StartupLean Startup
Lean Startup
SEA Tecnologia
 
Open Data
Open DataOpen Data
Open Data
SEA Tecnologia
 
Open data, scraping e thacks com Software Livre
Open data, scraping e thacks com Software LivreOpen data, scraping e thacks com Software Livre
Open data, scraping e thacks com Software LivreSEA Tecnologia
 
Agilidade dos projetos à empresa, uma história de Intracontágio
Agilidade dos projetos à empresa, uma história de IntracontágioAgilidade dos projetos à empresa, uma história de Intracontágio
Agilidade dos projetos à empresa, uma história de Intracontágio
SEA Tecnologia
 
Roadshow Brasília Novas funcionalidades Liferay 6
Roadshow Brasília Novas funcionalidades Liferay 6Roadshow Brasília Novas funcionalidades Liferay 6
Roadshow Brasília Novas funcionalidades Liferay 6
SEA Tecnologia
 
Roadshow Liferay no Brasil 2010
Roadshow Liferay no Brasil 2010Roadshow Liferay no Brasil 2010
Roadshow Liferay no Brasil 2010
SEA Tecnologia
 
Sem tesão não há solução
Sem tesão não há soluçãoSem tesão não há solução
Sem tesão não há solução
SEA Tecnologia
 
Empreendimentos em Rede
Empreendimentos em RedeEmpreendimentos em Rede
Empreendimentos em Rede
SEA Tecnologia
 

More from SEA Tecnologia (20)

Loomio how to Series - Working on a Discussion
Loomio how to Series - Working on a DiscussionLoomio how to Series - Working on a Discussion
Loomio how to Series - Working on a Discussion
 
Loomio how to Series - Creating a new Group of People
Loomio how to Series - Creating a new Group of PeopleLoomio how to Series - Creating a new Group of People
Loomio how to Series - Creating a new Group of People
 
Loomio how to Series - Creating a new Discussion
Loomio how to Series - Creating a new DiscussionLoomio how to Series - Creating a new Discussion
Loomio how to Series - Creating a new Discussion
 
Gerentes em Crise existencial - Existimos no Universo Ágil?
Gerentes em Crise existencial - Existimos no Universo Ágil?Gerentes em Crise existencial - Existimos no Universo Ágil?
Gerentes em Crise existencial - Existimos no Universo Ágil?
 
O curioso caso de Náutilus Button
O curioso caso de Náutilus ButtonO curioso caso de Náutilus Button
O curioso caso de Náutilus Button
 
Contratos de desenvolvimento de software para governo blue pill or red pill?
Contratos de desenvolvimento de software para governo  blue pill or red pill?Contratos de desenvolvimento de software para governo  blue pill or red pill?
Contratos de desenvolvimento de software para governo blue pill or red pill?
 
#Fail
#Fail#Fail
#Fail
 
Agilidade no Governo
Agilidade no GovernoAgilidade no Governo
Agilidade no Governo
 
Os benefícios e desafios da participação pública digital
Os benefícios e desafios da participação pública digitalOs benefícios e desafios da participação pública digital
Os benefícios e desafios da participação pública digital
 
A escola do século XXI deve ser ágil, enxuta e empreendedora.
A escola do século XXI deve ser ágil, enxuta e empreendedora.A escola do século XXI deve ser ágil, enxuta e empreendedora.
A escola do século XXI deve ser ágil, enxuta e empreendedora.
 
Lean Startup
Lean StartupLean Startup
Lean Startup
 
Open Data
Open DataOpen Data
Open Data
 
Open data, scraping e thacks com Software Livre
Open data, scraping e thacks com Software LivreOpen data, scraping e thacks com Software Livre
Open data, scraping e thacks com Software Livre
 
Agilidade dos projetos à empresa, uma história de Intracontágio
Agilidade dos projetos à empresa, uma história de IntracontágioAgilidade dos projetos à empresa, uma história de Intracontágio
Agilidade dos projetos à empresa, uma história de Intracontágio
 
Roadshow Brasília Novas funcionalidades Liferay 6
Roadshow Brasília Novas funcionalidades Liferay 6Roadshow Brasília Novas funcionalidades Liferay 6
Roadshow Brasília Novas funcionalidades Liferay 6
 
Roadshow Liferay no Brasil 2010
Roadshow Liferay no Brasil 2010Roadshow Liferay no Brasil 2010
Roadshow Liferay no Brasil 2010
 
Sem tesão não há solução
Sem tesão não há soluçãoSem tesão não há solução
Sem tesão não há solução
 
Empreendimentos em Rede
Empreendimentos em RedeEmpreendimentos em Rede
Empreendimentos em Rede
 
Java Profiling Tools
Java Profiling ToolsJava Profiling Tools
Java Profiling Tools
 
Misc Monitoring Tools
Misc Monitoring ToolsMisc Monitoring Tools
Misc Monitoring Tools
 

Recently uploaded

Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Albert Hoitingh
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
Matthew Sinclair
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
sonjaschweigert1
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
Dorra BARTAGUIZ
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
SOFTTECHHUB
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
Neo4j
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
KatiaHIMEUR1
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
Neo4j
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
Alpen-Adria-Universität
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
James Anderson
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
Neo4j
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
ControlCase
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
Jemma Hussein Allen
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
Uni Systems S.M.S.A.
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems S.M.S.A.
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
James Anderson
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
Alan Dix
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
Ana-Maria Mihalceanu
 

Recently uploaded (20)

Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
Encryption in Microsoft 365 - ExpertsLive Netherlands 2024
 
20240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 202420240605 QFM017 Machine Intelligence Reading List May 2024
20240605 QFM017 Machine Intelligence Reading List May 2024
 
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdfFIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
FIDO Alliance Osaka Seminar: Passkeys and the Road Ahead.pdf
 
A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...A tale of scale & speed: How the US Navy is enabling software delivery from l...
A tale of scale & speed: How the US Navy is enabling software delivery from l...
 
Elevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object CalisthenicsElevating Tactical DDD Patterns Through Object Calisthenics
Elevating Tactical DDD Patterns Through Object Calisthenics
 
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
Why You Should Replace Windows 11 with Nitrux Linux 3.5.0 for enhanced perfor...
 
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
GraphSummit Singapore | The Future of Agility: Supercharging Digital Transfor...
 
Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !Securing your Kubernetes cluster_ a step-by-step guide to success !
Securing your Kubernetes cluster_ a step-by-step guide to success !
 
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
GraphSummit Singapore | Graphing Success: Revolutionising Organisational Stru...
 
Video Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the FutureVideo Streaming: Then, Now, and in the Future
Video Streaming: Then, Now, and in the Future
 
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
Alt. GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using ...
 
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
GraphSummit Singapore | Enhancing Changi Airport Group's Passenger Experience...
 
PCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase TeamPCI PIN Basics Webinar from the Controlcase Team
PCI PIN Basics Webinar from the Controlcase Team
 
The Future of Platform Engineering
The Future of Platform EngineeringThe Future of Platform Engineering
The Future of Platform Engineering
 
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdfFIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
FIDO Alliance Osaka Seminar: The WebAuthn API and Discoverable Credentials.pdf
 
Microsoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdfMicrosoft - Power Platform_G.Aspiotis.pdf
Microsoft - Power Platform_G.Aspiotis.pdf
 
Uni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdfUni Systems Copilot event_05062024_C.Vlachos.pdf
Uni Systems Copilot event_05062024_C.Vlachos.pdf
 
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
GDG Cloud Southlake #33: Boule & Rebala: Effective AppSec in SDLC using Deplo...
 
Epistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI supportEpistemic Interaction - tuning interfaces to provide information for AI support
Epistemic Interaction - tuning interfaces to provide information for AI support
 
Monitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR EventsMonitoring Java Application Security with JDK Tools and JFR Events
Monitoring Java Application Security with JDK Tools and JFR Events
 

Minicurso de TestesOnRails

  • 2. 2
  • 5. O que testar? Quando testar? Quanto testar? Quantos asserts por teste? Teste quebrado mudar teste ou código? 5
  • 6. Contextualização Testes, Testes Automatizados, Desenvolvimento Orientado a Testes, Design Evolutivo, Ferramentas de Teste TestesOnRails Unit, Functionals, Integration,View,View Helpers, Routes, Performance, Mocks Shoulda, RSpec, RSpec-Rails, faker, Cucumber, Koujou 6
  • 9. Desenvolver Testar
  • 10. Desenvolver Testar
  • 11. ?
  • 12. ?
  • 13. $? ?
  • 14. $ cr iaç ão de sc ob er ta co rr eç ão
  • 15. X
  • 16.
  • 19. Teste Programa
  • 20. Teste Programa
  • 21. Teste Programa
  • 22. (...) public void meuTeste() { int par1 = 1; int par2 = 1; int result = Classe.soma(par1,par1); assertEquals(2, result); } (...) (...) public int soma(int a, int b) { // código } (...)
  • 23. (...) public void meuTeste() { int par1 = 1; Preparação int par2 = 1; int result = Classe.soma(par1,par1); assertEquals(2, result); } (...) (...) public int soma(int a, int b) { // código } (...)
  • 24. (...) public void meuTeste() { int par1 = 1; int par2 = 1; int result = Classe.soma(par1,par2); assertEquals(2, result); Exercício } (...) (...) public int soma(int a, int b) { // código } (...)
  • 25. (...) public void meuTeste() { int par1 = 1; int par2 = 1; int result = Classe.soma(par1,par1); } assertEquals(2, result); Verificação (...) (...) public int soma(int a, int b) { // código } (...)
  • 27. X
  • 28. X
  • 29. X
  • 30.
  • 31. 10 30
  • 32. 10 20 30 30
  • 33. 10 20 30 30 30 30
  • 34. 10 20 30 40 30 30 30 30
  • 35. 10 20 30 40 50 30 30 30 30 30
  • 36. 10 20 30 40 50 60 30 30 30 30 30 30
  • 37. 10 20 30 40 50 60 70 30 30 30 30 30 30 30
  • 38.
  • 39. public class Romanos { public static String parse(int entrada) { StringBuilder resultado = new StringBuilder(); if (entrada <= 3) { for (int i = 0; i < entrada; i++) resultado.append("I"); return resultado.toString(); } else if (entrada == 4) { return "IV"; } else if(entrada == 5){ return "V"; } else if (entrada < 9){ resultado.append("V"); return resultado.toString(); }else if (entrada == 9){ return "IX"; }else{ return "X"; } } }
  • 40. public static String parse(int entrada) { public static String parse(int entrada) { else if (entrada == 4) { return "IV"; public static String parse(int entrada) { else if (entrada == 4) { } else if(entrada == 5){ return "IV"; return "V"; else if (entrada == 4) { } else if(entrada == 5){ } return "IV"; return "V"; } else if(entrada == 5){ } } return "V"; } } } public class Romanos { public static String parse(int entrada) { StringBuilder resultado = new StringBuilder(); public static String parse(int entrada) { if (entrada <= 3) { for (int i = 0; i < entrada; i++) public static String parse(int entrada) { else if (entrada == 4) { resultado.append("I"); return "IV"; return resultado.toString(); else if (entrada == 4) { } else if(entrada == 5){ } return "IV"; return "V"; } else if(entrada == 5){ } else if (entrada == 4) { return "V"; return "IV"; } } } else if(entrada == 5){ return "V"; } } else if (entrada < 9){ resultado.append("V"); return resultado.toString(); }else if (entrada == 9){ return "IX"; }else{ return "X"; } } } public static String parse(int entrada) { public static String parse(int entrada) { else if (entrada == 4) { else if (entrada == 4) { return "IV"; return "IV"; } else if(entrada == 5){ } else if(entrada == 5){ return "V"; return "V"; } } } } public static String parse(int entrada) { else if (entrada == 4) { return "IV"; } else if(entrada == 5){ return "V"; } }
  • 41. public static String parse(int entrada) { public static String parse(int entrada) { else if (entrada == 4) { return "IV"; public static String parse(int entrada) { else if (entrada == 4) { } else if(entrada == 5){ return "IV"; return "V"; else if (entrada == 4) { } else if(entrada == 5){ } return "IV"; return "V"; } else if(entrada == 5){ } } return "V"; } } } public class Romanos { public static String parse(int entrada) { StringBuilder resultado = new StringBuilder(); public static String parse(int entrada) { if (entrada <= 3) { for (int i = 0; i < entrada; i++) public static String parse(int entrada) { else if (entrada == 4) { resultado.append("I"); return "IV"; return resultado.toString(); else if (entrada == 4) { } else if(entrada == 5){ } return "IV"; return "V"; } else if(entrada == 5){ } else if (entrada == 4) { return "V"; return "IV"; } } } else if(entrada == 5){ return "V"; } } else if (entrada < 9){ resultado.append("V"); return resultado.toString(); }else if (entrada == 9){ return "IX"; }else{ return "X"; } } } public static String parse(int entrada) { public static String parse(int entrada) { else if (entrada == 4) { else if (entrada == 4) { return "IV"; return "IV"; } else if(entrada == 5){ } else if(entrada == 5){ return "V"; return "V"; } } } } public static String parse(int entrada) { else if (entrada == 4) { return "IV"; } else if(entrada == 5){ return "V"; } }
  • 42. public static String parse(int entrada) { public static String parse(int entrada) { else if (entrada == 4) { return "IV"; public static String parse(int entrada) { else if (entrada == 4) { } else if(entrada == 5){ return "IV"; return "V"; else if (entrada == 4) { } else if(entrada == 5){ } return "IV"; return "V"; } else if(entrada == 5){ } } return "V"; } } } public class Romanos { public static String parse(int entrada) { StringBuilder resultado = new StringBuilder(); public static String parse(int entrada) { if (entrada <= 3) { for (int i = 0; i < entrada; i++) public static String parse(int entrada) { else if (entrada == 4) { resultado.append("I"); return "IV"; return resultado.toString(); else if (entrada == 4) { } else if(entrada == 5){ } return "IV"; return "V"; } else if(entrada == 5){ } else if (entrada == 4) { return "V"; return "IV"; } } } else if(entrada == 5){ return "V"; } } else if (entrada < 9){ resultado.append("V"); return resultado.toString(); }else if (entrada == 9){ return "IX"; }else{ return "X"; } } } public static String parse(int entrada) { public static String parse(int entrada) { else if (entrada == 4) { else if (entrada == 4) { return "IV"; return "IV"; } else if(entrada == 5){ } else if(entrada == 5){ return "V"; return "V"; } } } } public static String parse(int entrada) { else if (entrada == 4) { return "IV"; } else if(entrada == 5){ return "V"; } }
  • 43. evolvability maintainability mantenabilidade manutenibilidade manutenabilidade capacidade de manutenção
  • 44. Custo Tempo
  • 45. Custo Tempo
  • 47. GREEN
  • 48. RED teste GREEN
  • 49. RED código teste GREEN
  • 50. RED código teste GREEN refactoring
  • 52. RED Plan GREEN
  • 53. RED Plan Do GREEN
  • 54. RED Plan Do GREEN Check
  • 55. RED Plan Do Act GREEN Check
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66. ?
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 73. Foco RED GREEN
  • 74. Foco Ritmo RED GREEN
  • 75. Foco Ritmo RED Disciplina GREEN
  • 76. Foco Ritmo RED Disciplina Simplicidade GREEN
  • 77. Ferramentas (Java)
  • 83. Testes Testes Automáticos Desenvolvimento Orientado a Testes Design Evolutivo Ferramentas 46
  • 84. 47
  • 86. Quando se fala de testes, fala-se de... Mudanças Corretude Direcionamento Robustez Design evolutivo Documentação 49
  • 87. O que testar? caminho feliz caminhos alternativos erros conhecidos e esperados 50
  • 88. 51
  • 90. 53
  • 91. Kiwitter 54
  • 92. $ rails kiwitter create create app/controllers create app/helpers create app/models create app/views/layouts create config/environments create config/initializers create config/locales (...) create log/server.log create log/production.log create log/development.log create log/test.log 55
  • 93. kiwitter $ script/generate scaffold user login:string email:string password:string exists app/models/ exists app/controllers/ exists app/helpers/ create app/views/users exists app/views/layouts/ (...) create test/unit/user_test.rb create test/fixtures/users.yml create db/migrate create db/migrate/20090729120900_create_users.rb 56
  • 94. kiwitter $ script/server => Booting WEBrick => Rails 2.3.3 application starting on http://0.0.0.0:3000 => Call with -d to detach => Ctrl-C to shutdown server [2009-07-29 09:29:22] INFO WEBrick 1.3.1 [2009-07-29 09:29:22] INFO ruby 1.8.7 (2009-06-12) [powerpc-darwin9] [2009-07-29 09:29:22] INFO WEBrick::HTTPServer#start: pid=54915 port=3000 57
  • 95. kiwitter $ rake db:migrate (in ...maredeagilidade_ceara/labs/rails_test/kiwitter) == CreateUsers: migrating ======================================== -- create_table(:users) -> 0.0082s == CreateUsers: migrated (0.0094s) ================================= 58
  • 96. Unit Functional Integration Performance Tests 59
  • 97. kiwitter $ rake -T rake test rake test:benchmark rake test:functionals rake test:integration rake test:plugins rake test:profile rake test:recent rake test:uncommitted rake test:units 60
  • 98. kiwitter $ rake test:units Started ........FE Finished in 1.181401 seconds. 61
  • 101. Rails environments test development production 64
  • 102. 65
  • 103. Fixtures 66
  • 104. Test fixture refers to the fixed state used as a baseline for running tests in software testing. The purpose of a test fixture is to ensure that there is a well known and fixed environment in which tests are run so that results are repeatable. Some people call this the test context. http://en.wikipedia.org/wiki/Test_fixture 67
  • 105. 68
  • 107. Inicialização da base database.yml Identificação dos arquivos de testes test/**/*.rb Para cada teste identificação dos métodos de testes 70
  • 108. Para cada método de teste test “should xxx yyy” 1. carrega fixtures test/fixtures/users.yml 2. executa setup 3. executa o teste .....FE 4. executa teardown 5. “descarrega” fixtures rollback ou delete 71
  • 109. ios ár n it s U s t e Te 72
  • 111. Rails Unit Tests 1. fixtures 2. setup 3. test/unit/*_test.rb 4. teardown 74
  • 112. Test::Unit::TestCase assert assert_not_same assert_block assert_nothing_raised assert_equal assert_nothing_thrown assert_in_delta assert_operator assert_instance_of assert_raise assert_kind_of assert_raises assert_match assert_respond_to assert_nil assert_same assert_no_match assert_send assert_not_equal assert_throws assert_not_nil 75
  • 115. assert assert_nothing_thrown assert_block assert_operator assert_equal assert_raise assert_in_delta assert_raises assert_instance_of assert_respond_to assert_kind_of assert_same assert_match assert_send assert_nil assert_throws assert_no_match build_message assert_not_equal flunk assert_not_nil use_pp= assert_not_same assert_difference assert_nothing_raised assert_no_difference 78
  • 116. Kiwitter 79
  • 117. Kiwitter 80
  • 118. 81
  • 119. kiwitter $ rake test:units ... /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/ 1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/ unit/helpers/users_helper_test.rb" "test/unit/ user_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader Started . Finished in 0.201504 seconds. 1 tests, 1 assertions, 0 failures, 0 errors 82
  • 120. 83
  • 121. kiwitter $ rake test:units /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader.rb" "test/unit/helpers/users_helper_test.rb" "test/ unit/user_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader Started .F Finished in 0.378072 seconds. 1) Failure: test_should_require_login(UserTest) [/test/unit/user_test.rb:16]: <nil> is not true. 2 tests, 2 assertions, 1 failures, 0 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 84
  • 122. 85
  • 123. kiwitter $ rake test:units /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/ gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader.rb" "test/unit/helpers/ users_helper_test.rb" "test/unit/user_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/ rake-0.8.7/lib/rake/rake_test_loader Started .. Finished in 0.178493 seconds. 2 tests, 2 assertions, 0 failures, 0 errors 86
  • 124. Labs Desenvolver Orientado a Testes Validação de obrigatoriedade de senha e email Validação de unicidade do login Validação formato do email 87
  • 125. 88
  • 126. 89
  • 127. kiwitter $ rake test:units /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader.rb" "test/unit/helpers/users_helper_test.rb" "test/unit/user_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader Started ..E Finished in 0.322179 seconds. 1) Error: test_should_sign_in_only_when_valid_credentials_are_given(UserTest): NoMethodError: undefined method `signin' for #<Class:0x1a761f0> /test/unit/user_test.rb:22:in `test_should_sign_in_only_when_valid_credentials_are_given' 3 tests, 2 assertions, 0 failures, 1 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 90
  • 128. 1) Error: test_should_sign_in_only_when_valid_credentials_are_given(UserTest): ArgumentError: wrong number of arguments (2 for 0) /test/unit/user_test.rb:22:in `signin' /test/unit/user_test.rb:22:in `test_should_sign_in_only_when_valid_credentials_are_given' 3 tests, 2 assertions, 0 failures, 1 errors 91
  • 132. 1) Failure: test_should_sign_in_only_when_valid_credentials_are_given(UserT est) [/test/unit/user_test.rb:22]: <nil> is not true. 3 tests, 3 assertions, 1 failures, 0 errors 1) Failure: test_should_sign_in_only_when_valid_credentials_are_given(UserT est) [/test/unit/user_test.rb:23]: <false> is not true. 3 tests, 4 assertions, 1 failures, 0 errors Problema quando se tem vários asserts num mesmo test case. 95
  • 133. Refactoring 96
  • 134. kiwitter $ rake test:units /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader.rb" "test/unit/helpers/users_helper_test.rb" "test/unit/user_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader Started .FF.. Finished in 0.421486 seconds. 1) Failure: test_should_not_sign_in_when_invalid_password_is_given(UserTest) [/test/unit/ user_test.rb:27]: <false> is not true. 2) Failure: test_should_not_sign_in_when_invalid_username_is_given(UserTest) [/test/unit/ user_test.rb:31]: <false> is not true. 5 tests, 5 assertions, 2 failures, 0 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 97
  • 136. Fixtures mecanismo para criação de massa de dados de testes 99
  • 137. 100
  • 138. 101
  • 139. kiwitter $ rake test:units /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/ gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/unit/ helpers/users_helper_test.rb" "test/unit/user_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader Started ..... Finished in 0.367962 seconds. 5 tests, 5 assertions, 0 failures, 0 errors 102
  • 140. Labs Testes unitários como TDD para criação (post) de mensagens (update) por um usuário 103
  • 142. HTTP Req ? 105
  • 143. Test::Unit::TestCase ActiveSupport::TestCase + ActiveController::TestCase + Rails Functional Tests 106
  • 144. ActiveController::TestCase Métodos Mock Objects “Hashes” get @controller session post @request cookies put @response flash delete assigns xhr @response.body session[:user_id] 107
  • 145. ActiveController::TestCase assert_dom_equal assert_select assert_dom_not_equal assert_select_email assert_valid assert_select_encoded assert_redirected_to assert_select_rjs assert_response css_select assert_template response_from_page_or_rjs assert_generates unescape_rjs assert_recognizes assert_no_tag assert_routing assert_tag 108
  • 146. 1. setup params = {:project_id => @project.id.to_s, :task_id => @task.id.to_s} session = {:user_id => 12345} 2. teste <método http> <método do controller> <params> <session> <flash> get :index post :create params session put :update {:notice => “Task updated”} delete ... 109
  • 147. Não testa rotas! *Sempre* enviar parâmetros HTTP como string 110
  • 148. st atus assert_ response ‘c onteúdo’ assert_t emplate ionam ento redirec t asser t_redirec 111
  • 149. assert_response 200 assert_response 404 assert_response :success assert_response :missing assert_template “index” assert_template “users/new” assert_redirect_to :controller => task, :id => 3 assert_redirect_to new_task_url assert_redirect_to @task 112
  • 151. Kiwitter 114
  • 152. Kiwitter 115
  • 153. kiwitter $ rake test:functionals /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/ rake/rake_test_loader.rb" "test/functional/users_controller_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader Started F...... Finished in 0.618077 seconds. 1) Failure: test_should_create_user(UsersControllerTest) [/test/functional/ users_controller_test.rb:16]: "User.count" didn't change by 1. <3> expected but was <2>. 7 tests, 9 assertions, 1 failures, 0 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 116
  • 154. 117
  • 155. kiwitter $ rake test:functionals /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/ gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/ functional/users_controller_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader Started ....... Finished in 0.883527 seconds. 7 tests, 10 assertions, 0 failures, 0 errors 118
  • 156. 119
  • 157. kiwitter $ script/generate controller sessions new exists app/controllers/ exists app/helpers/ create app/views/sessions exists test/functional/ exists test/unit/helpers/ create app/controllers/sessions_controller.rb create test/functional/sessions_controller_test.rb create app/helpers/sessions_helper.rb create test/unit/helpers/sessions_helper_test.rb create app/views/sessions/new.html.erb 120
  • 158. 121
  • 159. 122
  • 160. kiwitter $ rake test:functionals /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/functional/ users_controller_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader Started F....... Finished in 0.842942 seconds. 1) Failure: test_should_authenticate_user(SessionsControllerTest) [/test/functional/ sessions_controller_test.rb:8]: <nil> expected to not be nil. assert_not_nil 8 tests, 12 assertions, 1 failures, 0 errors assigns(:user) rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 123
  • 161. 124
  • 162. kiwitter $ rake test:functionals /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/functional/users_controller_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader Started F....... Finished in 0.57468 seconds. assert_template "users/home" 1) Failure: test_should_authenticate_user(SessionsControllerTest) [/test/functional/ sessions_controller_test.rb:13]: expecting <"users/home"> but rendering with <"sessions/create.html.erb"> 8 tests, 13 assertions, 1 failures, 0 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 125
  • 163. 126
  • 164. kiwitter $ rake test:functionals /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/ rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/ functional/users_controller_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader Started F....... inconsistência Finished in 0.610806 seconds. 1) Failure: test_should_authenticate_user(SessionsControllerTest) [/test/functional/ sessions_controller_test.rb:9]: Expected response to be a <:success>, but was <302> 8 tests, 11 assertions, 1 failures, 0 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 127
  • 165. 128
  • 166. kiwitter $ rake test:functionals /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/ rake/rake_test_loader.rb" "test/functional/sessions_controller_test.rb" "test/ functional/users_controller_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader Started redirect não implica na F....... renderização da página de Finished in 0.99891 seconds. destino 1) Failure: test_should_authenticate_user(SessionsControllerTest) [/test/functional/ sessions_controller_test.rb:13]: expecting <"users/home"> but rendering with <""> 8 tests, 13 assertions, 1 failures, 0 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 129
  • 167. 130
  • 168. kiwitter alegomes$ rake test:functionals /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/ gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/ functional/sessions_controller_test.rb" "test/functional/ users_controller_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader Started ........ Finished in 0.547148 seconds. 8 tests, 12 assertions, 0 failures, 0 errors 131
  • 169. Labs Testar/implementar autenticação de usuário inválido @user não deve ser criada usuário deve ser redirecionado para página de login Testar/implementar post de mensagem 132
  • 171. Req Controller 1 Req Controller 2 Req Controller 3 ? 134
  • 172. Testes de Integração Testes de Aceitação 135
  • 173. Integração desenvolvedores X linguagem ruby Aceitação clientes linguagem natural 136
  • 174. TD não participa do ciclo de 137
  • 175. {post, get, delete...}_via_redirect segue todos os redirects follow_redirect! segue apenas um redirect redirect? verifica se a última req foi redirect https! faz com que todas as reqs pareçam HTTPs host! altera o servidor da app 138
  • 176. 139
  • 177. kiwitter $ script/generate integration_test post_updates exists test/integration/ create test/integration/post_updates_test.rb 140
  • 178. 141
  • 179. kiwitter $ rake test:integration /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/ gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/ integration/post_updates_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader Started . Finished in 0.255598 seconds. 1 tests, 2 assertions, 0 failures, 0 errors 142
  • 180. Lab? 143
  • 183. Tradeoff 146
  • 184. assert_select("form") verifica a existência da tag <form> <span>Maré de Agilidade</span> assert_select("span", "Maré de Agilidade") assert_select("span", /Agilidade/) 147
  • 185. 148
  • 186. 149
  • 187. 150
  • 188. kiwitter $ rake test:integration /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/ gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/ integration/post_updates_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/ lib/rake/rake_test_loader Started . Finished in 0.943481 seconds. 1 tests, 3 assertions, 0 failures, 0 errors 151
  • 189. 1) Failure: test_should_post_an_update(PostUpdatesTest) [/test/ integration/post_updates_test.rb:15]: Expected at least 1 element matching "div#welcome_messageeeeeeeee", found 0. <false> is not true. 1 tests, 3 assertions, 1 failures, 0 errors 152
  • 190. Testes dos View Helpers 153
  • 191. 154
  • 192. 155
  • 193. 156
  • 194. kiwitter $ rake test:units /opt/local/bin/ruby -I"lib:test" "/opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/ rake_test_loader.rb" "test/unit/helpers/sessions_helper_test.rb" "test/unit/helpers/ updates_helper_test.rb" "test/unit/helpers/users_helper_test.rb" "test/unit/ update_test.rb" "test/unit/user_test.rb" Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader Started .......E Finished in 0.510089 seconds. 1) Error: test_should_display_user_greetings(UsersHelperTest): NoMethodError: undefined method `display_greetings' for #<UsersHelperTest: 0x1ba7e84> /test/unit/helpers/users_helper_test.rb:10:in `test_should_display_user_greetings' 8 tests, 8 assertions, 0 failures, 1 errors rake aborted! Command failed with status (1): [/opt/local/bin/ruby -I"lib:test" "/opt/loc...] (See full trace by running task with --trace) 157
  • 195. 8 tests, 9 assertions, 0 failures, 0 errors 158
  • 196. Bom senso 159
  • 198. ActionController::Assertions::RoutingAssertions assert_generates assert_generates "/items", :controller => "items", :action => "index" assert_recognizes assert_recognizes {:controller => 'items', :action => 'create'}, {:path => 'items', :method => :post} assert_routing assert_routing '/home', :controller => 'home', :action => 'index' http://api.rubyonrails.org/classes/ActionController/Assertions/RoutingAssertions.html 161
  • 199. Labs View View Helper Routes 162
  • 200. Mock Objects 163
  • 201. Quem não tem cão... 164
  • 203. Objeto real indisponível ou de difícil acesso. Reprodução de cenários complexos. 166
  • 204. Mocks Aren't Stubs The term 'Mock Objects' has become a popular one to describe special case objects that mimic real objects for testing. Most language environments now have frameworks that make it easy to create mock objects. What's often not realized, however, is that mock objects are but one form of special case test object, one that enables a different style of testing. In this article I'll explain how mock objects work, how they encourage testing based on behavior verification, and how the community around them uses them to develop a different style of testing. http://www.martinfowler.com/articles/mocksArentStubs.html 167
  • 205. Stu 168
  • 206. Objeto falso que retorna um valor predeterminado para uma chamada de método objeto.stubs(:metodo).and_returns("alguma coisa") “ignore a implementacao real de objeto.metodo e retorne ‘alguma coisa’” se objeto.metodo for invocado retornará "alguma coisa" se objeto.metodo NÃO for invocado nada acontecerá 169
  • 207. 170
  • 208. 17 tests, 28 assertions, 0 failures, 0 errors 171
  • 209. 17 tests, 26 assertions, 1 failures, 0 errors 172
  • 211. semelhante ao stub, com uma diferença objeto.stubs(:metodo).adn_returns("alguma coisa") se objeto.metodo for invocado retornará "alguma coisa" se objeto.metodo NÃO for invocado o teste falhará 174
  • 212. 1) Failure: test_mock_example(UserTest) [/test/unit/user_test.rb:35]: not all expectations were satisfied unsatisfied expectations: - expected exactly once, not yet invoked: #<Mock:0x1884090>.email(any_parameters) satisfied expectations: - expected exactly once, already invoked once: #<Mock:0x1884090>.login(any_parameters) 9 tests, 12 assertions, 1 failures, 0 errors rake aborted! 175
  • 213. 9 tests, 13 assertions, 0 failures, 0 errors 176
  • 214. mocks returns raises any_instance with pattern matches 177
  • 215. User.any_instance.expects(:login).returns(nil) user.login deve ser executado apenas uma única vez 178
  • 217. http://flexmock.rubyforge.org http://mocha.rubyforge.org http://double-ruby.rubyforge.org http://rspec.info 180
  • 220. context setup do @u = .... end should “alguma coisa” do assert.... end end 183
  • 221. $ sudo gem install thoughtbot-shoulda --source=http://gems.github.com Password: Successfully installed thoughtbot-shoulda-2.10.2 1 gem installed Installing ri documentation for thoughtbot-shoulda-2.10.2... Installing RDoc documentation for thoughtbot-shoulda-2.10.2... http://wiki.github.com/thoughtbot/shoulda/installation 184
  • 224. assert_accepts assert_contains assert_does_not_contain assert_rejects assert_same_elements http://dev.thoughtbot.com/shoulda/classes/Shoulda/Assertions.html 187
  • 227. 190
  • 228. should_change should_render_without_layout should_not_change should_respond_with should_assign_to should_respond_with_content_type should_filter_params should_return_from_session should_not_assign_to should_route should_not_set_the_flash should_set_session should_redirect_to should_set_the_flash_to should_render_template should_render_a_form should_render_with_layout should_render_page_with_metadata http://dev.thoughtbot.com/shoulda/classes/Shoulda/Macros.html http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActionController/Macros.html http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActionView/Macros.html 191
  • 229. should_allow_mass_assignment_of should_have_named_scope should_allow_values_for should_have_one should_belong_to should_have_readonly_attributes should_ensure_length_at_least should_not_allow_mass_assignment_of should_ensure_length_in_range should_not_allow_values_for should_ensure_length_is should_only_allow_numeric_values_for should_ensure_value_in_range should_protect_attributes should_have_and_belong_to_many should_require_acceptance_of should_have_class_methods should_require_attributes should_have_db_column should_require_unique_attributes should_have_db_columns should_validate_acceptance_of should_have_index should_validate_numericality_of should_have_indices should_validate_presence_of should_have_instance_methods should_validate_uniqueness_of should_have_many http://dev.thoughtbot.com/shoulda/classes/Shoulda/ActiveRecord/Macros.html 192
  • 231. 194 “ RSpec is the original Behaviour Driven Development framework for Ruby. http://rspec.info
  • 232. Test Driven * corretude qualidade < 100% = 100% rebola a ordem não no mato importa 195
  • 233. testes passado descrição de algo pronto X especificação futuro descrição de algo inexistente 196
  • 234. $ sudo gem install rspec Password: ************************************************** Thank you for installing rspec-1.2.8 Please be sure to read History.rdoc and Upgrade.rdoc for useful information about this release. ************************************************** Successfully installed rspec-1.2.8 1 gem installed Installing ri documentation for rspec-1.2.8... Installing RDoc documentation for rspec-1.2.8... (...) 197
  • 235. kiwitter_rspec $ script/generate rspec exists lib/tasks create lib/tasks/rspec.rake create script/autospec create script/spec create script/spec_server exists spec create spec/rcov.opts create spec/spec.opts create spec/spec_helper.rb 198
  • 236. kiwitter_rspec $ rake -T rake spec rake spec:plugin_doc rake spec:clobber_rcov rake spec:plugins rake spec:controllers rake spec:plugins:rspec_on_rails rake spec:db:fixtures:load rake spec:rcov rake spec:doc rake spec:server:restart rake spec:helpers rake spec:server:start rake spec:integration rake spec:server:status rake spec:lib rake spec:server:stop rake spec:models rake spec:views 199
  • 237. describe funcionalidade it “should do A” do ... end it “should do B” do actual.should expected end ... end 200
  • 238. 201
  • 239. 202
  • 240. should_not should have_at_most should be_true be_instance_of have_exactly should be_false should_not helper should be_nil be_an_instance_of should include should should be_close should_not include be_[arbitrary_predicate] should_not be_close inspect_object should_not be_nil be_instance_of should match should_not be_kind_of should_not match be_[arbitrary_predicate] should change should raise_error be_a should_not change should_not raise_error should be_kind_of should eql should respond_to should be_a_kind_of should_not eql should_not respond_to should_not be_kind_of should equal should satisfy should_not should_not equal should_not satisfy be_a_kind_of should exist simple_matcher be_an should_not exist should throw_symbol should be_instance_of should have should_not should should_not have throw_symbol be_an_instance_of should have_at_least wrap_expectation http://rspec.rubyforge.org/rspec/1.2.8/classes/Spec/Matchers.html 203
  • 241. expected.XXXXX? expected.should be_XXXXX expected.should be_a_XXXXX expected.should be_an_XXXXX expected.should have_key(:k) expected.has_key?(:k) expected.should have(10).items expected.should have(10).laranjas expected.should have(10).filhos 204
  • 242. 205
  • 243. 206
  • 244. $ sudo gem install rspec-rails Password: ************************************************** Thank you for installing rspec-rails-1.2.7.1 If you are upgrading, do this in each of your rails apps that you want to upgrade: $ ruby script/generate rspec Please be sure to read History.rdoc and Upgrade.rdoc for useful information about this release. ************************************************** Successfully installed rspec-rails-1.2.7.1 1 gem installed Installing ri documentation for rspec-rails-1.2.7.1... Installing RDoc documentation for rspec-rails-1.2.7.1... (...) 207
  • 245. $ rails kiwitter_rspec create create app/controllers create app/helpers create app/models create app/views/layouts create config/environments create config/initializers create config/locales create db create doc (...) 208
  • 246. kiwitter_rspec $ script/generate rspec_scaffold user login:string password:string email:string (...) create spec/controllers/ create spec/routing/ create spec/models/ create spec/helpers/ create spec/fixtures/ create spec/views/users create spec/integration/ (...) create spec/views/users/new.html.erb_spec.rb create spec/views/users/show.html.erb_spec.rb create spec/integration/users_spec.rb create db/migrate create db/migrate/20090802144903_create_users.rb route map.resources :users 209
  • 247. script/generate rspec_scaffold update user:references message:text script/generate migration update_user_join 210
  • 248. Mais testes gerados que o tradicional Test::Unit 211
  • 250. Model Spec 213
  • 252. Controller Spec response.should response.should_not { be_success be_redirect redirect_to(url ou hash) render_template(‘users/home’) 215
  • 253. View Spec 216
  • 254. View Spec Test::Unit RSpec assigns(@user) assigns[:user] session[:user_id] session[:user_id] cookies[“user_id”] cookies[“user_id”] flash[:notice] flash[:notice] 217
  • 255. View Spec { be_valid have_rjs response.should have_tag response.should_not have_text have_text send_email response.should have_tag “xxx” do ... end { with_encoded with_tag without_tag http://rspec.rubyforge.org/rspec-rails/1.2.7.1/classes/Spec/Rails/Matchers.html 218
  • 257. Helper Spec 220
  • 258. { spec spec:controllers spec:helpers spec:integration rake spec:lib spec:models spec:plugins spec:views 221
  • 259. kiwitter_rspec $ rake spec:models .. Finished in 1.703168 seconds 2 examples, 0 failures 222
  • 260. Lab 223
  • 261. faker Faker (...) is used to easily generate fake data http://faker.rubyforge.org 224
  • 262. kiwitter $ sudo gem install faker Password: Successfully installed faker-0.3.1 1 gem installed Installing ri documentation for faker-0.3.1... Installing RDoc documentation for faker-0.3.1... 225
  • 264. Maida McDermott April Metz Rowena Jakubowski Anita Lueilwitz Alena Ferry 227
  • 266. puts Faker::Lorem.paragraphs(2) Rerum quos hic et. Autem harum ea asperiores consequatur libero et. Ipsum cumque dicta optio voluptate. Et quia officia minus iure vitae. Ducimus delectus unde neque odio voluptas inventore minima. Fugiat nihil error incidunt nihil quo natus omnis. Quis consequatur aut totam ad. Doloribus nihil officiis nobis rerum tempora. Nam eos mollitia delectus assumenda veritatis. Itaque voluptatem repudiandae odit provident error ut. Perspiciatis est facilis sit quis et qui vel. Hic corrupti recusandae aliquid possimus. Et error ad ut voluptatem non labore. Accusantium non tempore aut assumenda architecto enim. Quasi eos et dicta. Tempore quia optio eos pariatur fugiat. Est neque molestias aliquid et. Dolor cum nemo tempora. Eum ratione esse quam magni officiis dolor. Earum maxime sit eaque optio laboriosam tempora voluptatibus. Quo illum ipsa sit. Ea sequi id et sunt nemo quibusdam maxime. Ab voluptate nesciunt maxime rerum iure explicabo in. Sed quidem dignissimos est officia necessitatibus sed qui. Similique odit qui id nostrum corporis autem quas enim. Sunt placeat eum architecto tempora non. Est libero aut repellat mollitia. Quisquam non quia et id est repellat qui aspernatur. Animi ut sit quaerat. Dignissimos enim esse autem qui sed aut optio a. Debitis facilis aut eaque alias exercitationem quia impedit. Maiores vitae id odio est inventore. Aut accusamus et et vel sint. Quo ducimus dolor nemo quia libero autem. Assumenda est voluptas debitis in libero. Illo sit deleniti tenetur nisi. Reiciendis et odit fugiat velit hic. Quo nisi deserunt sit. 229
  • 267. http://faker.rubyforge.org/rdoc Array rand shuffle Faker::Address city city_prefix city_suffix secondary_address street_address street_name street_suffix uk_country uk_county uk_postcode us_state us_state_abbr zip_code Faker::Company bs catch_phrase name suffix Faker::Internet domain_name domain_suffix domain_word email free_email user_name Faker::Lorem paragraph paragraphs sentence sentences words Faker::Name first_name last_name name prefix suffix Faker::PhoneNumber phone_number 230
  • 269. 232
  • 271. DSL features scenarios Rails Test steps Rails Code 233
  • 272. $ sudo gem install cucumber Password: Successfully installed term-ansicolor-1.0.4 Successfully installed polyglot-0.2.6 Successfully installed treetop-1.3.0 Successfully installed diff-lcs-1.1.2 Successfully installed builder-2.1.2 Successfully installed cucumber-0.3.92 6 gems installed Installing ri documentation for term-ansicolor-1.0.4... Installing ri documentation for polyglot-0.2.6... Installing ri documentation for treetop-1.3.0... (...) Installing RDoc documentation for diff-lcs-1.1.2... Installing RDoc documentation for builder-2.1.2... Installing RDoc documentation for cucumber-0.3.92... 234
  • 273. kiwitter $ script/plugin install git://github.com/brynary/webrat.git Initialized empty Git repository in .../kiwitter/vendor/plugins/webrat/.git/ remote: Counting objects: 275, done. remote: Compressing objects: 100% (236/236), done. remote: Total 275 (delta 36), reused 170 (delta 20) Receiving objects: 100% (275/275), 5.07 MiB | 154 KiB/s, done. Resolving deltas: 100% (36/36), done. From git://github.com/brynary/webrat * branch HEAD -> FETCH_HEAD = Webrat - Ruby Acceptance Testing for Web applications ... == Description Webrat lets you quickly write expressive and robust acceptance tests for a Ruby web application. 235
  • 274. kiwitter $ sudo gem install nokogiri Building native extensions. This could take a while... Successfully installed nokogiri-1.3.3 1 gem installed Installing ri documentation for nokogiri-1.3.3... Installing RDoc documentation for nokogiri-1.3.3... 236
  • 275. kiwitter $ script/generate cucumber create features/step_definitions create features/step_definitions/webrat_steps.rb create config/environments/cucumber.rb create features/support create features/support/env.rb create features/support/paths.rb exists lib/tasks create lib/tasks/cucumber.rake create script/cucumber 237
  • 276. Feature: caso de uso/estória em teste In order objetivo da funcionalidade Stakeholder o que o stakeholder deseja Background Given pré-condições And mais pré-condições | login | email | password | | alegomes | alegomes@gmail.com | ale123 | | luciana | lu@brasilia.net | xuxu | Scenario: cenário/fluxo em teste Given pré-condições When ação do usuário Then resultado da ação do usuário 238
  • 277. kiwitter $ script/generate feature users_and_updates exists features/step_definitions create features/manage_users_and_updates.feature create features/step_definitions/users_and_updates_steps.rb 239
  • 279. Teste de aceitação gerado pelo Cucumber 241
  • 280. modificado para o kiwitter 242
  • 281. kiwitter $ rake features /opt/local/bin/ruby -I "/opt/local/lib/ruby/gems/1.8/gems/cucumber-0.3.92/lib:lib" "/opt/local/lib/ ruby/gems/1.8/gems/cucumber-0.3.92/bin/cucumber" --format pretty features/ manage_users_and_updates.feature Feature: Post update messages In order to make my life widely public As a User I want to post short messages describing what I am doing Scenario: Post new messages # features/manage_users_and_updates.feature:6 Given I am at users home page # features/manage_users_and_updates.feature:7 And I have entered a text message up to 140 chars # features/manage_users_and_updates.feature:8 When I press post # features/manage_users_and_updates.feature:9 Then the message should be registered # features/manage_users_and_updates.feature:10 1 scenario (1 undefined) 4 steps (4 undefined) 0m0.653s ... 243
  • 282. ... You can implement step definitions for undefined steps with these snippets: Given /^I am at users home page$/ do pending end Given /^I have entered a text message up to 140 chars$/ do pending end When /^I press post$/ do pending end Then /^the message should be registered$/ do pending end 244
  • 285. ... You can implement step definitions for undefined steps with these snippets: Given /^I am at users home page$/ do pending end Given /^I have entered a text message up to 140 chars$/ do pending end When /^I press post$/ do pending end Then /^the message should be registered$/ do pending end 247
  • 286. kiwitter $ rake features /opt/local/bin/ruby -I "/opt/local/lib/ruby/gems/1.8/gems/cucumber-0.3.92/lib:lib" "/opt/ local/lib/ruby/gems/1.8/gems/cucumber-0.3.92/bin/cucumber" --format pretty features/ manage_users_and_updates.feature Feature: Post update messages In order to make my life widely public As a User I want to post short messages describing what I am doing Scenario: Post new messages Given I am at users home page TODO (Cucumber::Pending) features/manage_users_and_updates.feature:7:in `Given I am at users home page' And I have entered a text message up to 140 chars When I press post Then the message should be registered 1 scenario (1 pending) 4 steps (3 skipped, 1 pending) 0m0.134s 248
  • 287. Given I am at users home page TODO (Cucumber::Pending) features/manage_users_and_updates.feature:7:in `Given I am at users home page' Given /^I am at users home page$/ do visit "users/home" end 249
  • 288. kiwitter $ rake features ... Scenario: Post new messages users_controller.home Given I am at users home page And I have entered a text message up to 140 chars TODO (Cucumber::Pending) features/manage_users_and_updates.feature:8:in `And I have entered a text message up to 140 chars' When I press post Then the message should be registered 1 scenario (1 pending) 4 steps (2 skipped, 1 pending, 1 passed) 0m0.260s 250
  • 289. And I have entered a text message up to 140 chars TODO (Cucumber::Pending) features/manage_users_and_updates.feature:8:in `And I have entered a text message up to 140 chars' 251
  • 290. kiwitter $ cucumber features/manage_users_and_updates.feature Feature: Post update messages In order to make my life widely public As a User I want to post short messages describing what I am doing Scenario: Post new messages users_controller.home Given I am at users home page And I have entered a text message up to 140 chars When I press post TODO (Cucumber::Pending) features/manage_users_and_updates.feature:9:in `When I press post' Then the message should be registered 1 scenario (1 pending) 4 steps (1 skipped, 1 pending, 2 passed) 0m0.305s 252
  • 291. When I press post TODO (Cucumber::Pending) features/manage_users_and_updates.feature:9:in `When I press post' 253
  • 292. kiwitter $ cucumber features/manage_users_and_updates.feature Feature: Post update messages In order to make my life widely public As a User I want to post short messages describing what I am doing Scenario: Post new messages users_controller.home Given I am at users home page And I have entered a text message up to 140 chars When I press post Then the message should be registered TODO (Cucumber::Pending) features/manage_users_and_updates.feature:10:in `Then the message should be registered' 1 scenario (1 pending) 4 steps (1 pending, 3 passed) 0m0.282s 254
  • 293. Then the message should be registered TODO (Cucumber::Pending) features/manage_users_and_updates.feature:10:in `Then the message should be registered' ? 255
  • 294. webrat http://github.com/brynary/webrat/tree/master 256
  • 295. kiwitter $ script/plugin install git://github.com/brynary/webrat.git Initialized empty Git repository in .../kiwitter/vendor/plugins/webrat/.git/ remote: Counting objects: 275, done. remote: Compressing objects: 100% (236/236), done. remote: Total 275 (delta 36), reused 170 (delta 20) Receiving objects: 100% (275/275), 5.07 MiB | 125 KiB/s, done. Resolving deltas: 100% (36/36), done. From git://github.com/brynary/webrat * branch HEAD -> FETCH_HEAD (= Webrat - Ruby Acceptance Testing for Web applications - http://gitrdoc.com/brynary/webrat - http://groups.google.com/group/webrat - http://webrat.lighthouseapp.com/ - http://github.com/brynary/webrat - #webrat on Freenode (...) 257
  • 299. $ sudo gem install rcov Password: Building native extensions. This could take a while... Successfully installed rcov-0.8.1.2.0 1 gem installed Installing ri documentation for rcov-0.8.1.2.0... Installing RDoc documentation for rcov-0.8.1.2.0... 261
  • 300. $ rcov --version rcov 0.8.1.2 2007-11-22 262
  • 301. kiwitter $ ./script/plugin install --force http://svn.codahale.com/rails_rcov + ./MIT-LICENSE + ./README + ./tasks/rails_rcov.rake http://agilewebdevelopment.com/plugins/rails_rcov 263
  • 302. kiwitter $ rake -T | grep rcov rake doc:plugins:rails_rcov rake test:profile:clobber_rcov rake spec:clobber_rcov rake test:profile:rcov rake spec:rcov rake test:recent:clobber_rcov rake test:benchmark:clobber_rcov rake test:recent:rcov rake test:benchmark:rcov rake test:test:clobber_rcov rake test:functionals:clobber_rcov rake test:test:rcov rake test:functionals:rcov rake test:uncommitted:clobber_rcov rake test:integration:clobber_rcov rake test:uncommitted:rcov rake test:integration:rcov rake test:units:clobber_rcov rake test:plugins:clobber_rcov rake test:units:rcov rake test:plugins:rcov 264
  • 303. kiwitter $ rake test:units:rcov 10 tests, 13 assertions, 1 failures, 1 errors +----------------------------------------------------+-------+-------+--------+ | File | Lines | LOC | COV | +----------------------------------------------------+-------+-------+--------+ |.../ruby/1.8/gems/sqlite3-ruby-1.2.5/lib/sqlite3.rb | 1 | 1 | 100.0% | |...gems/sqlite3-ruby-1.2.5/lib/sqlite3/constants.rb | 49 | 44 | 97.7% | |.../gems/sqlite3-ruby-1.2.5/lib/sqlite3/database.rb | 721 | 340 | 40.3% | |...3-ruby-1.2.5/lib/sqlite3/driver/native/driver.rb | 219 | 180 | 48.3% | |....8/gems/sqlite3-ruby-1.2.5/lib/sqlite3/errors.rb | 68 | 58 | 84.5% | |...8/gems/sqlite3-ruby-1.2.5/lib/sqlite3/pragmas.rb | 271 | 190 | 45.8% | |...gems/sqlite3-ruby-1.2.5/lib/sqlite3/resultset.rb | 180 | 114 | 72.8% | |...gems/sqlite3-ruby-1.2.5/lib/sqlite3/statement.rb | 231 | 128 | 50.0% | |...ems/sqlite3-ruby-1.2.5/lib/sqlite3/translator.rb | 109 | 64 | 20.3% | |...1.8/gems/sqlite3-ruby-1.2.5/lib/sqlite3/value.rb | 57 | 44 | 29.5% | |app/controllers/application_controller.rb | 48 | 21 | 23.8% | |app/controllers/sessions_controller.rb | 32 | 9 | 22.2% | |app/controllers/updates_controller.rb | 85 | 60 | 13.3% | |app/controllers/users_controller.rb | 89 | 63 | 14.3% | |app/helpers/application_helper.rb | 3 | 2 | 100.0% | |app/helpers/sessions_helper.rb | 3 | 2 | 100.0% | |app/helpers/updates_helper.rb | 2 | 2 | 100.0% | |app/helpers/users_helper.rb | 8 | 5 | 40.0% | |app/models/update.rb | 5 | 4 | 100.0% | |app/models/user.rb | 8 | 6 | 100.0% | +----------------------------------------------------+-------+-------+--------+ |Total | 2189 | 1337 | 46.3% | 265 +----------------------------------------------------+-------+-------+--------+
  • 304. 266
  • 305. Q&A

Editor's Notes

  1. Pouco tempo e muito conte&amp;#xFA;do Turma heterog&amp;#xEA;nea Cada um segue seu ritmo Pouca teoria e muita pr&amp;#xE1;tica
  2. Comecemos falando de testes
  3. Se voc&amp;#xEA; falar com qualquer pessoa comum sobre testes, ela associar&amp;#xE1; &amp;#xE0; realiza&amp;#xE7;&amp;#xE3;o de rotinas de verifica&amp;#xE7;&amp;#xE3;o de algo anteriormente constru&amp;#xED;do.
  4. Se voc&amp;#xEA; falar com qualquer pessoa comum sobre testes, ela associar&amp;#xE1; &amp;#xE0; realiza&amp;#xE7;&amp;#xE3;o de rotinas de verifica&amp;#xE7;&amp;#xE3;o de algo anteriormente constru&amp;#xED;do.
  5. O problema, entretanto, &amp;#xE9; grande tempo entre a constru&amp;#xE7;&amp;#xE3;o e a verifica&amp;#xE7;&amp;#xE3;o.
  6. O problema, entretanto, &amp;#xE9; grande tempo entre a constru&amp;#xE7;&amp;#xE3;o e a verifica&amp;#xE7;&amp;#xE3;o.
  7. O problema, entretanto, &amp;#xE9; grande tempo entre a constru&amp;#xE7;&amp;#xE3;o e a verifica&amp;#xE7;&amp;#xE3;o.
  8. A medida que o tempo passa, manuten&amp;#xE7;&amp;#xF5;es ficam mais caras.
  9. E a&amp;#xED;, o cen&amp;#xE1;rio mais comum, e come&amp;#xE7;ar a guerra fria entre os que constroem e os que verificam.
  10. Convergindo na pior afirma&amp;#xE7;&amp;#xE3;o de qualquer membro de equipe: &amp;#x201C;n&amp;#xE3;o &amp;#xE9; problema meu&amp;#x201D;
  11. Como forma de aliviar, dentre outras coisas, essa disputa entre desenvolvedores e testadores, foi proposta uma metodologia de desenvolvimento chamada TDD.
  12. Quando se faz teste, al&amp;#xE9;m do c&amp;#xF3;digo programa em si, deve-se escrever outro c&amp;#xF3;digo que verifique o programa que, quando &amp;#xE9; executado....
  13. Quando se faz teste, al&amp;#xE9;m do c&amp;#xF3;digo programa em si, deve-se escrever outro c&amp;#xF3;digo que verifique o programa que, quando &amp;#xE9; executado....
  14. ...pode passar...
  15. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  16. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  17. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  18. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  19. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  20. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  21. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  22. Eu tenho um c&amp;#xF3;digo e v&amp;#xE1;rios testes que o suportam.
  23. O impacto de qualquer modifica&amp;#xE7;&amp;#xE3;o no c&amp;#xF3;digo....
  24. ...&amp;#xE9; imediatamente apontado por seus testes.
  25. Testes automaticos tratam de algo t&amp;#xE3;o importante que mal sabemos traduzir....
  26. Controla o crescimento do custo das mudan&amp;#xE7;as que, tradicionalmente, &amp;#xE9; descontrolado.
  27. Iterativo vs Incremental Iterativo!??! S&amp;#xF3; na constru&amp;#xE7;&amp;#xE3;o. Big Design Upfront vs Design Evolutivo
  28. Iterativo vs Incremental Iterativo!??! S&amp;#xF3; na constru&amp;#xE7;&amp;#xE3;o. Big Design Upfront vs Design Evolutivo
  29. Big design upf-ront
  30. Mudan&amp;#xE7;as: rastreamento autom&amp;#xE1;tico de impactos de modifica&amp;#xE7;&amp;#xF5;es Robustez: evitar apps fr&amp;#xE1;geis cujos bugs sempre voltam Direcionamento: &amp;#x201C;s&amp;#xED;ndrome da folha em branco&amp;#x201D;
  31. Vamos fazer um Twitter.
  32. Quando se cria uma app Rails, v&amp;#xE1;rios testes s&amp;#xE3;o automaticamente gerados...
  33. Para execu&amp;#xE7;&amp;#xE3;o dos teste, utiliza-se instru&amp;#xE7;&amp;#xF5;es rake.
  34. Quando se executa os tese
  35. Toda execu&amp;#xE7;&amp;#xE3;o de testes no Rails utiliza o seu ambiente de testes, sem impactar na base de desenvolvimento ou nos dados de produ&amp;#xE7;&amp;#xE3;o.
  36. Fixtures &amp;#xE9; o mecanismo do Rails para cria&amp;#xE7;&amp;#xE3;o da massa de testes.
  37. Na verdade, Fixtures &amp;#xE9; uma t&amp;#xE9;cnica n&amp;#xE3;o exclusiva do Rails
  38. ...discutida at&amp;#xE9; em livros...
  39. Testes unit&amp;#xE1;rios do Rails s&amp;#xE3;o compostos por recursos b&amp;#xE1;sicos de testes do Ruby mais recursos espec&amp;#xED;ficos do Rails
  40. O funcionamento dos testes unit&amp;#xE1;rios seguem a regra geral, com detalhe para o passo 3.
  41. V&amp;#xE1;rias asser&amp;#xE7;&amp;#xF5;es v&amp;#xEA;m do Ruby Test::Unit::TestCase
  42. Do Ruby...
  43. Do Rails...
  44. Teste gerado pelo Rails.
  45. Criemos um teste pra checar o ActiveRecord (apenas para fins did&amp;#xE1;ticos)
  46. Oops, tudo funcionou de cara. Mas claro, o ActiveRecord j&amp;#xE1; est&amp;#xE1; pronto!
  47. Fa&amp;#xE7;amos um novo teste.
  48. TODO: u.valid? u.errors.invalid?(:email) mensagem de erro no assert associacao yml helper
  49. Implementar funcionalidade de Login.
  50. Defini&amp;#xE7;&amp;#xE3;o do m&amp;#xE9;todo &amp;#x2018;signin&amp;#x2019;
  51. O m&amp;#xE9;todo signin retorna &amp;#x2018;null&amp;#x2019;, mas o teste espera &amp;#x2018;true&amp;#x2019;
  52. Teste espera &amp;#x2018;false&amp;#x2019; mas c&amp;#xF3;digo retorna &amp;#x2018;true&amp;#x2019;
  53. Agora sim. Ficou mais claro qual teste est&amp;#xE1; falhando.
  54. N&amp;#xE3;o encontrou no banco qualquer registro com login = &amp;#x201C;alegomes&amp;#x201D; e password = &amp;#x201C;ale123&amp;#x201D;
  55. Dicas: - Criar scaffold de updates
  56. Resumo dos testes funcionais: teste enviar requisi&amp;#xE7;&amp;#xE3;o HTTP ao controller e verifica se a resposta enviada coincide com a resposta esperada.
  57. Testes unit&amp;#xE1;rios do Rails s&amp;#xE3;o compostos por recursos b&amp;#xE1;sicos de testes do Ruby mais recursos espec&amp;#xED;ficos do Rails
  58. Novidades
  59. Asser&amp;#xE7;&amp;#xF5;es
  60. Teste pode passar, mas pode n&amp;#xE3;o existir rota definidar pra ele. Uma par&amp;#xE2;metro n&amp;#xE3;o string pode fazer o teste passar, mas n&amp;#xE3;o funcionar&amp;#xE1; para o usu&amp;#xE1;rio, pois o browser sempre manda string.
  61. assert_response {200,300...} ou {:success, :redirect, :missing, :error} assert_template &amp;#x201C;index&amp;#x201D; (n&amp;#xE3;o checa o conte&amp;#xFA;do!) assert_redirect n&amp;#xE3;o segue o redirecionamento
  62. Exemplos
  63. N&amp;#xE3;o repita os mesmos testes nos dois lugares.
  64. Pra cada controlador...
  65. ...tem-se seu respectivo teste.
  66. Testes funcionais gerados pelo scaffold n&amp;#xE3;o est&amp;#xE3;o passando.
  67. A requisi&amp;#xE7;&amp;#xE3;o post est&amp;#xE1; passando um usu&amp;#xE1;rio sem informar nenhum atributo, contrariando nossa valida&amp;#xE7;&amp;#xE3;o.
  68. Agora sim!
  69. Prossigamos com a funcionaldiade de login.
  70. Gera&amp;#xE7;&amp;#xE3;o de um novo controlador de sess&amp;#xF5;es, respons&amp;#xE1;vel pelo login e logout do usu&amp;#xE1;rio.
  71. Teste funcional criado para o novo controller.
  72. Mais de perto.... Esta &amp;#xE9; a forma mais comum de se testar um controlador: assert_response assert_not_nil assert_template
  73. Teste funcional criado falhando na linha 8: assert_not_nil assigns(:user)
  74. Controlador invocando Model para autentica&amp;#xE7;&amp;#xE3;o do usu&amp;#xE1;rio e disponibiliza&amp;#xE7;&amp;#xE3;o da inst&amp;#xE2;ncia @user pra camada View.
  75. Falha agora no assert da linha 13: assert_template &quot;users/home&quot;
  76. Se o usu&amp;#xE1;rio tiver sido autenticado com sucesso, redirecione-o para sua p&amp;#xE1;gina home.
  77. Nosso teste est&amp;#xE1; inconsistente! Em um momento, ele verifica o retorno de sucesso (200) da requisi&amp;#xE7;&amp;#xE3;o. Em outro, ele checa se a requisi&amp;#xE7;&amp;#xE3;o gerou um redirecionamento de p&amp;#xE1;gina (300).
  78. Mudan&amp;#xE7;a no teste de &amp;#x2018;assert_response :success&amp;#x2019; para &amp;#x2018;assert_response :redirect&amp;#x2019;
  79. ATEN&amp;#xC7;&amp;#xC3;O! O redirect n&amp;#xE3;o implica no render do template de destino. Logo, n&amp;#xE3;o podemos usar assert_template com redirect.
  80. Mudan&amp;#xE7;as no teste: - Substitui&amp;#xE7;&amp;#xE3;o do assert_template por assert_redirect_to - Elimina&amp;#xE7;&amp;#xE3;o do &amp;#x2018;assert_response :redirect&amp;#x2019;, cuja verifica&amp;#xE7;&amp;#xE3;o j&amp;#xE1; &amp;#xE9; impl&amp;#xED;cita no assert_redirected_to
  81. Fa&amp;#xE7;a um monte de chamadas a v&amp;#xE1;rios controladores e verifique o resultado.
  82. Tratam de conceitos diferentes.