Você está na página 1de 74

Test-driven Development no Rails

Comeando seu projeto com o p direito


2007, Nando Vieira http://simplesideias.com.br

O que iremos ver?

slides = Array.new slides << O que TDD? slides << Por que testar slides << Um pequeno exemplo slides << TDD no Rails slides << Fixtures slides << Testes unitrios slides << Testes funcionais slides << Testes de integrao slides << Mocks & Stubs slides << Dvidas?

O que TDD?

Test-driven Development ou Desenvolvimento Guiado por Testes Uma tcnica de desenvolvimento de software Ficou conhecida como um aspecto do XP

O que TDD?

Kent Beck (TDD by Example, 2003): 1. Escreva um teste que falhe antes de escrever qualquer cdigo 2. Elimine toda duplicao (refactoring) 3. Resposta rpida a pequenas mudanas 4. Escreva seus prprios testes

O que TDD?

Processo:
1. Escreva o teste 2. Veja os testes falharem

3. Escreva o cdigo

5. Refatore o cdigo

4. Veja os testes passarem

Porque testar

Isso no me impediu de cometer a tresloucada loucura de publicar minha aplicao utilizando Rails 1.2.3 apenas um dia aps o lanamento deles. Devo estar ficando doido mesmo. Ou isso ou tenho testes.

Thiago Arrais Motiro, no Google Groups Ruby-Br

Porque testar

Voc: escrever cdigos melhores escrever cdigos mais rapidamente identificar erros mais facilmente no usar F5 nunca mais!

Um pequeno exemplo
test_calculator.rb class TestCalculator < Test::Unit::TestCase def setup @calc = Calculator.new end def teardown @calc = nil end def test_sum assert_equal(2, @calc.sum(1, 1), "1 + 1 = 2") end def test_subtract assert_equal(1, @calc.subtract(2, 1), 2 - 1 = 1") end def test_multiply assert_equal(4, @calc.multiply(2, 2), 2 x 2 = 4") end def test_divide assert_equal(2, @calc.sum(4, 2), 4 / 2 = 2") assert_raise(ZeroDivisionError) { @calc.divide(2, 0) } end end

Um pequeno exemplo
test_calculator.rb class TestCalculator < Test::Unit::TestCase def setup @calc = Calculator.new end def teardown @calc = nil end def test_sum assert_equal(2, @calc.sum(1, 1), "1 + 1 = 2") end def test_subtract assert_equal(1, @calc.subtract(2, 1), 2 - 1 = 1") end def test_multiply assert_equal(4, @calc.multiply(2, 2), 2 x 2 = 4") end def test_divide assert_equal(2, @calc.sum(4, 2), 4 / 2 = 2") assert_raise(ZeroDivisionError) { @calc.divide(2, 0) } end end

Um pequeno exemplo
test_calculator.rb class TestCalculator < Test::Unit::TestCase def setup @calc = Calculator.new end def teardown @calc = nil end def test_sum assert_equal(2, @calc.sum(1, 1), "1 + 1 = 2") end def test_subtract assert_equal(1, @calc.subtract(2, 1), 2 - 1 = 1") end def test_multiply assert_equal(4, @calc.multiply(2, 2), 2 x 2 = 4") end def test_divide assert_equal(2, @calc.sum(4, 2), 4 / 2 = 2") assert_raise(ZeroDivisionError) { @calc.divide(2, 0) } end end

Um pequeno exemplo
test_calculator.rb class TestCalculator < Test::Unit::TestCase def setup @calc = Calculator.new end def teardown @calc = nil end def test_sum assert_equal(2, @calc.sum(1, 1), "1 + 1 = 2") end def test_subtract assert_equal(1, @calc.subtract(2, 1), 2 - 1 = 1") end def test_multiply assert_equal(4, @calc.multiply(2, 2), 2 x 2 = 4") end def test_divide assert_equal(2, @calc.sum(4, 2), 4 / 2 = 2") assert_raise(ZeroDivisionError) { @calc.divide(2, 0) } end end

Um pequeno exemplo
test_calculator.rb class TestCalculator < Test::Unit::TestCase def setup @calc = Calculator.new end def teardown @calc = nil end def test_sum assert_equal(2, @calc.sum(1, 1), "1 + 1 = 2") end def test_subtract assert_equal(1, @calc.subtract(2, 1), 2 - 1 = 1") end def test_multiply assert_equal(4, @calc.multiply(2, 2), 2 x 2 = 4") end def test_divide assert_equal(2, @calc.sum(4, 2), 4 / 2 = 2") assert_raise(ZeroDivisionError) { @calc.divide(2, 0) } end end

Um pequeno exemplo
test_calculator.rb class TestCalculator < Test::Unit::TestCase def setup @calc = Calculator.new end def teardown @calc = nil end def test_sum assert_equal(2, @calc.sum(1, 1), "1 + 1 = 2") end def test_subtract assert_equal(1, @calc.subtract(2, 1), 2 - 1 = 1") end def test_multiply assert_equal(4, @calc.multiply(2, 2), 2 x 2 = 4") end def test_divide assert_equal(2, @calc.sum(4, 2), 4 / 2 = 2") assert_raise(ZeroDivisionError) { @calc.divide(2, 0) } end end

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

execute os testes:

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

execute os testes: todos eles devem falhar


$~ ruby test_calculator.rb Loaded suite test Started EEEE Finished in 0.0 seconds. 1) Error: test_divide(TestCalculator): NameError: uninitialized constant TestCalculator::Calculator test.rb:24:in `setup' ... 4 tests, 0 assertions, 0 failures, 4 errors

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

execute os testes: todos eles devem falhar


$~ ruby test_calculator.rb Loaded suite test Started EEEE Finished in 0.0 seconds. 1) Error: test_divide(TestCalculator): NameError: uninitialized constant TestCalculator::Calculator test.rb:24:in `setup' ... 4 tests, 0 assertions, 0 failures, 4 errors

4 erros: nosso cdigo no passou no teste

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o primeiro mtodo:

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o primeiro mtodo: rode os testes


$~ ruby test_calculator.rb Loaded suite test Started EEE. Finished in 0.0 seconds. 1) Error: test_divide(TestCalculator): NoMethodError: undefined method `divide' for #<Calculator: 0x2e2069c> test.rb:44:in `test_divide ... 4 tests, 1 assertions, 0 failures, 3 errors

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o primeiro mtodo: rode os testes


$~ ruby test_calculator.rb Loaded suite test Started EEE. Finished in 0.0 seconds. 1) Error: test_divide(TestCalculator): NoMethodError: undefined method `divide' for #<Calculator: 0x2e2069c> test.rb:44:in `test_divide ... 4 tests, 1 assertions, 0 failures, 3 errors

1 assero: nosso cdigo passou no teste

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n2 - n1 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o mtodo seguinte:

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n2 - n1 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o mtodo seguinte: rode os testes


$~ ruby test_calculator.rb Loaded suite test Started EF.E Finished in 0.0 seconds. 1) Failure: test_subtract(TestCalculator) [test.rb:35]: 2 - 1 = 1. <1> expected but was <-1>. ... 4 tests, 1 assertions, 1 failures, 2 errors

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n2 - n1 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o mtodo seguinte: rode os testes


$~ ruby test_calculator.rb Loaded suite test Started EF.E Finished in 0.0 seconds. 1) Failure: test_subtract(TestCalculator) [test.rb:35]: 2 - 1 = 1. <1> expected but was <-1>. ... 4 tests, 1 assertions, 1 failures, 2 errors

1 falha: nosso cdigo no passou no teste

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n2 - n1 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o mtodo seguinte: rode os testes


$~ ruby test_calculator.rb Loaded suite test Started EF.E Finished in 0.0 seconds. 1) Failure: test_subtract(TestCalculator) [test.rb:35]: 2 - 1 = 1. <1> expected but was <-1>. ... 4 tests, 1 assertions, 1 failures, 2 errors

1 falha: nosso cdigo no passou no teste devia ser n1 - n2

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

corrija o mtodo que falhou:

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

corrija o mtodo que falhou: rode os testes


$~ ruby test_calculator.rb Loaded suite test Started E..E Finished in 0.0 seconds. 1) Error: test_divide(TestCalculator): NoMethodError: undefined method `divide' for #<Calculator: 0x2e2069c> test.rb:44:in `test_divide ... 4 tests, 2 assertions, 0 failures, 2 errors

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

corrija o mtodo que falhou: rode os testes


$~ ruby test_calculator.rb Loaded suite test Started E..E Finished in 0.0 seconds. 1) Error: test_divide(TestCalculator): NoMethodError: undefined method `divide' for #<Calculator: 0x2e2069c> test.rb:44:in `test_divide ... 4 tests, 2 assertions, 0 failures, 2 errors

2 asseres: nosso cdigo passou no teste

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

continue o processo:

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

continue o processo: execute os testes


$~ ruby test_calculator.rb ... 4 tests, 3 assertions, 0 failures, 1 errors

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

continue o processo: execute os testes


$~ ruby test_calculator.rb ... 4 tests, 3 assertions, 0 failures, 1 errors

s mais um: ufa!

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o ltimo mtodo:

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o ltimo mtodo: execute os testes


$~ ruby test_calculator.rb Loaded suite test Started .... Finished in 0.0 seconds. 4 tests, 5 assertions, 0 failures, 0 errors

Um pequeno exemplo
calculator.rb class Calculator def sum(n1, n2) n1 + n2 end def subtract(n1, n2) n1 - n2 end def multiply(n1, n2) n1 * n2 end def divide(n1, n2) n1 / n2 end end

escreva o ltimo mtodo: execute os testes


$~ ruby test_calculator.rb Loaded suite test Started .... Finished in 0.0 seconds. 4 tests, 5 assertions, 0 failures, 0 errors

5 asseres, nenhuma falha/erro: cdigo perfeito!

TDD no Rails

Testar uma aplicao no Rails muito simples Os testes ficam no diretrio test Os arquivos de testes so criados para voc Apenas um comando: rake test Dados de testes: fixtures Testes unitrios, funcionais, integrao e performance Mocks & Stubs

Fixtures

Contedo inicial do modelo Ficam sob o diretrio test/fixtures SQL, CSV ou YAML
Modelo Artist

Tabela artists

Fixture artists.yml

Fixtures
test/fixtures/artists.yml

nofx: id: 1 name: NOFX url: http://nofxofficialwebsite.com created_at: <%= Time.now.strftime(:db) %> millencolin: id: 2 name: Millencolin url: http://millencolin.com created_at: <%= 3.days.ago.strftime(:db) %>

Testes unitrios

Testes unitrios validam modelos Ficam sob o diretrio test/unit Arquivo gerado pelo Rails: <model>_test.rb

script/generate model Artist

test/unit/artist_test.rb

Testes unitrios
test/unit/artist_test.rb

require File.dirname(__FILE__) + '/../test_helper' class ArtistTest < Test::Unit::TestCase fixtures :artists # Replace this with your real tests. def test_truth assert true end end

Testes unitrios
test/unit/artist_test.rb

require File.dirname(__FILE__) + '/../test_helper' class ArtistTest < Test::Unit::TestCase fixtures :artists def test_should_require_name artist = create(:name => nil) assert_not_nil artist.errors.on(:name), ":name should have had an error" assert !artist.valid?, "artist should be invalid" end private def create(options={}) Artist.create({ :name => 'Death Cab For Cutie', :url => 'http://deathcabforcutie.com' }.merge(options)) end end

Testes unitrios
app/models/artist.rb

class Artist < ActiveRecord::Base end

execute os testes:

Testes unitrios
app/models/artist.rb

class Artist < ActiveRecord::Base end

execute os testes: rake test:units


$~ rake test:units Loaded suite test Started F Finished in 0.094 seconds. 1) Failure: test_should_require_name(ArtistTest) [./test/ unit/artist_test.rb:8]: :name should have had an error. <nil> expected to not be nil. 1 tests, 1 assertions, 1 failures, 0 errors

Testes unitrios
app/models/artist.rb

class Artist < ActiveRecord::Base end

execute os testes: rake test:units


$~ rake test:units Loaded suite test Started F Finished in 0.094 seconds. 1) Failure: test_should_require_name(ArtistTest) [./test/ unit/artist_test.rb:8]: :name should have had an error. <nil> expected to not be nil. 1 tests, 1 assertions, 1 failures, 0 errors

o teste falhou: era esperado!

Testes unitrios
app/models/artist.rb

class Artist < ActiveRecord::Base validates_presence_of :name end

adicione a validao:

Testes unitrios
app/models/artist.rb

class Artist < ActiveRecord::Base validates_presence_of :name end

adicione a validao: execute os testes


$~ rake test:units Loaded suite test Started . Finished in 0.062 seconds. 1 tests, 2 assertions, 0 failures, 0 errors

Testes unitrios
app/models/artist.rb

class Artist < ActiveRecord::Base validates_presence_of :name end

adicione a validao: execute os testes


$~ rake test:units Loaded suite test Started . Finished in 0.062 seconds. 1 tests, 2 assertions, 0 failures, 0 errors

nenhuma falha: voila!

Testes funcionais

Testes funcionais validam controles Ficam sob o diretrio test/functional Template e/ou requisio Arquivo gerado pelo Rails: <controller>_test.rb script/generate controller artists

test/functional/artists_controller_test.rb

Testes funcionais
test/functional/artists_controller_test.rb

require File.dirname(__FILE__) + '/../test_helper require artists_controller # Re-raise errors caught by the controller. class ArtistsController; def rescue_action(e) raise e end; end class ArtistsControllerTest < Test::Unit::TestCase def setup @controller = ArtistsController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end # Replace this with your real tests. def test_truth assert true end end

Testes funcionais
test/functional/artists_controller_test.rb

... class ArtistsControllerTest < Test::Unit::TestCase def setup @controller = ArtistsController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end def test_index_page get index_path assert_response :success assert_template index assert_select h1, Bands that sound like... assert_select form, {:count => 1, :method} => get do assert_select input#name, :count => 1 assert_select input[type=submit], :count => 1 end end end

Testes funcionais
test/functional/artists_controller_test.rb

... class ArtistsControllerTest < Test::Unit::TestCase def setup @controller = ArtistsController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new end def test_index_page get index_path assert_response :success assert_template index

requisio: verificando a resposta

assert_select h1, Bands that sound like... assert_select form, {:count => 1, :method} => get do assert_select input#name, :count => 1 assert_select input[type=submit], :count => 1 end end end

template: verificando o markup

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Error: test_index_page(ArtistsControllerTest): ActionController::UnknownAction: No action responded to index ... ./test/functional/artists_controller_test.rb:15:in `test_index_page' 1 tests, 0 assertions, 0 failures, 1 errors

execute os testes:

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Error: test_index_page(ArtistsControllerTest): ActionController::UnknownAction: No action responded to index ... ./test/functional/artists_controller_test.rb:15:in `test_index_page' 1 tests, 0 assertions, 0 failures, 1 errors

execute os testes: eles devem falhar

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Error: test_index_page(ArtistsControllerTest): ActionController::UnknownAction: No action responded to index ... ./test/functional/artists_controller_test.rb:15:in `test_index_page' 1 tests, 0 assertions, 0 failures, 1 errors

execute os testes: eles devem falhar

1 erro: ele j era esperado

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Error: test_index_page(ArtistsControllerTest): ActionController::UnknownAction: No action responded to index ... ./test/functional/artists_controller_test.rb:15:in `test_index_page' 1 tests, 0 assertions, 0 failures, 1 errors

execute os testes: eles devem falhar

action: ns ainda no a criamos

1 erro: ele j era esperado

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Failure: test_index_page(ArtistsControllerTest) [selector_assertions.rb:281:in `assert_select' ./test/functional/artists_controller_test.rb:19:in `test_index_page']: Expected at least 1 elements, found 0. <false> is not true. 1 tests, 3 assertions, 1 failures, 0 errors

crie o template index.rhtml:

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Failure: test_index_page(ArtistsControllerTest) [selector_assertions.rb:281:in `assert_select' ./test/functional/artists_controller_test.rb:19:in `test_index_page']: Expected at least 1 elements, found 0. <false> is not true. 1 tests, 3 assertions, 1 failures, 0 errors

crie o template index.rhtml: execute os testes

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Failure: test_index_page(ArtistsControllerTest) [selector_assertions.rb:281:in `assert_select' ./test/functional/artists_controller_test.rb:19:in `test_index_page']: Expected at least 1 elements, found 0. <false> is not true. 1 tests, 3 assertions, 1 failures, 0 errors

crie o template index.rhtml: execute os testes

1 erro: ele j era esperado

Testes funcionais
~$ rake test:functionals Loaded suite test Started E Finished in 0.094 seconds. 1) Failure:

crie o template index.rhtml: execute os testes

template: nenhum cdigo HTML

test_index_page(ArtistsControllerTest) [selector_assertions.rb:281:in `assert_select' ./test/functional/artists_controller_test.rb:19:in `test_index_page']: Expected at least 1 elements, found 0. <false> is not true. 1 tests, 3 assertions, 1 failures, 0 errors

1 erro: ele j era esperado

Testes funcionais
app/views/artists/index.rhtml

<h1>Bands that sound like...</h1> <% form_tag 'view', {:method => :get} do %> <p> <%= text_field_tag :name %> <%= submit_tag View' %> </p> <% end %>

cdigo HTML:

Testes funcionais
app/views/artists/index.rhtml

<h1>Bands that sound like...</h1> <% form_tag 'view', {:method => :get} do %> <p> <%= text_field_tag :name %> <%= submit_tag View' %> </p> <% end %>

cdigo HTML: execute os testes


~$ rake test:functionals Loaded suite test Started . Finished in 0.094 seconds. 1 tests, 9 assertions, 0 failures, 0 errors

Testes funcionais
app/views/artists/index.rhtml

<h1>Bands that sound like...</h1> <% form_tag 'view', {:method => :get} do %> <p> <%= text_field_tag :name %> <%= submit_tag View' %> </p> <% end %>

cdigo HTML: execute os testes


~$ rake test:functionals Loaded suite test Started . Finished in 0.094 seconds. 1 tests, 9 assertions, 0 failures, 0 errors

yep: tudo certo! erros: nenhum para contar histria

Testes de integrao

Testes de integrao validam (duh) a integrao entre diferentes controllers Ficam sob o diretrio test/integration Rails no gera arquivo automaticamente: voc escolhe!

script/generate integration_test artist_stories

test/integraton/artist_stories_test.rb

Testes de integrao
test/integration/artist_stories_test.rb

require File.dirname(__FILE__) + '/../test_helper' class ArtistStoriesTest < ActionController::IntegrationTest # fixtures :your, :models # Replace this with your real tests. def test_truth assert true end end

Testes de integrao
test/integration/artist_stories_test.rb

require File.dirname(__FILE__) + '/../test_helper' class ArtistStoriesTest < ActionController::IntegrationTest fixtures :artists, :albums def test_user_viewing_artist_and_album # user accessing index page get "/" assert_response :success assert_template "index" # searching for an artist get artist_search_path(artists(:millencolin).slug) assert_response :redirect assert_redirected_to "/artists/#{artists(:millencolin).slug}" # viewing album "life on a plate" get album_path(albums(:life_on_a_plate)) assert_response :success assert_template "view" end end

Testes de integrao
test/integration/artist_stories_test.rb

require File.dirname(__FILE__) + '/../test_helper' class ArtistStoriesTest < ActionController::IntegrationTest fixtures :artists, :albums def test_user_viewing_artist_and_album # user accessing index page get "/" assert_response :success assert_template "index"

controller: /

# searching for an artist get artist_search_path(artists(:millencolin).slug) assert_response :redirect assert_redirected_to "/artists/#{artists(:millencolin).slug}" # viewing album "life on a plate" get album_path(albums(:life_on_a_plate)) assert_response :success assert_template "view" end end

controller: /artists/search

controller: /albums/

Testes de integrao

Testes funcionais em um nvel mais alto: DSL Leitura mais fcil, impossvel! Use o mtodo open_session
open_session do |session| # Do everything you need! end

Testes de integrao
test/integration/artist_stories_test.rb
class ArtistStoriesTest < ActionController::IntegrationTest fixtures :artists, :albums def test_artist_story artist = artists(:millencolin) user = new_session user.search_artist artist user.view_album artist.albums.first end private def new_session open_session do |session| def session.search_artist(artist) get search_artist(artist.name) assert_response :redirect assert_redirected_to artist_path(artist.slug) end def session.view_album(album) get album_path(album.slug) assert_response :success assert_template 'view' end end end end

Testes de integrao
test/integration/artist_stories_test.rb
class ArtistStoriesTest < ActionController::IntegrationTest fixtures :artists, :albums def test_artist_story artist = artists(:millencolin) user = new_session user.search_artist artist user.view_album artist.albums.first end

user = new_session user.search_artist artist user.view_album artist.albums.first

private def new_session open_session do |session| def session.search_artist(artist) get search_artist(artist.name) assert_response :redirect assert_redirected_to artist_path(artist.slug) end def session.view_album(album) get album_path(album.slug) assert_response :success assert_template 'view' end end end end

Testes de integrao
test/integration/artist_stories_test.rb
class ArtistStoriesTest < ActionController::IntegrationTest fixtures :artists, :albums def test_artist_story artist = artists(:millencolin) user = new_session user.search_artist artist user.view_album artist.albums.first end

user = new_session user.search_artist artist user.view_album artist.albums.first

private def new_session open_session do |session| def session.search_artist(artist) get search_artist(artist.name) assert_response :redirect assert_redirected_to artist_path(artist.slug) end def session.view_album(album) get album_path(album.slug) assert_response :success assert_template 'view' end end end end

melhor, impossvel!

Mocks & Stubs

Cdigos que eliminam o acesso a um recurso Ficam sob o diretrio test/mocks/test Deve ter o mesmo nome do arquivo e estrutura da classe/mdulo que voc quer substituir

RAILS_ROOT/lib/launch_missile.rb

test/mocks/<RAILS_ENV>/launch_missile.rb

Mocks & Stubs


lib/feed.rb

require open-uri class Feed def load(url) open URI.parse(url).read end end

Mocks & Stubs


lib/feed.rb

require open-uri class Feed def load(url) open URI.parse(url).read end end no o ideal: a) pode ser lento; b) pode no estar disponvel; c) imagine se fosse transao de pagamento!

Mocks & Stubs


test/mocks/test/feed.rb

require open-uri class Feed def load(url) File.new(#{RAILS_ROOT}/test/fixtures/feed.xml).read end end

Mocks & Stubs


test/mocks/test/feed.rb

require open-uri class Feed def load(url) File.new(#{RAILS_ROOT}/test/fixtures/feed.xml).read end end muito mais fcil e rpido: faa quantos pagamentos quiser!

Dvidas?

Você também pode gostar