Reputation: 349
To make it simple, I have a model Canvas and a model Block.
On each of my canvas-view (which is just a basic table), I have some forms intended to update some blocks contents.
I want to test with RSPEC and Capybara whether or not changes are properly commited.
So I've got this line :
page.driver.execute_script("document.getElementById('block_#{(index+1).to_s}').submit();")
Which sends to my BlocksController
class BlocksController < ApplicationController
def update
b=Block.find_by_id_case_and_canvas_id(params[:block][:id_case], params[:block][:canvas_id])
b.update_attributes(params[:block])
redirect_to "/canvas/"+b.canvas_id.to_s
end
end
And I can assure you that my canvas-view and all my controllers/models works properly.
But tests fail with this error :
NoMethodError: undefined method `update_attributes' for nil:NilClass
So I've taken a look into my test logs and saw that Database_cleaner seems to delete some tables before I've finished my work :
Processing by BlocksController#update as HTML
Block Load (0.4ms) SELECT "blocks".* FROM "blocks" WHERE "blocks"."canvas_id" = 1 AND "blocks"."id_case" = 1 LIMIT 1
Parameters: {"utf8"=>"✓", "block"=>{"content"=>"1234567890", "id_case"=>"1", "canvas_id"=>"1"}, "id"=>"1"}
(141.8ms) DELETE FROM "blocks";
Block Load (0.5ms) SELECT "blocks".* FROM "blocks" WHERE "blocks"."id_case" = 1 AND "blocks"."canvas_id" = 1 LIMIT 1
And most of the time, as you can see, the UPDATE request isn't even tried. (I saw it one time by running tests again and again).
So my question is, do someone know how to retard those deletions ?
Thank you a lot !
PS :
Database Cleaner is configured just as in this link :
I've tried to change strategies several times but nothing helped.
Upvotes: 1
Views: 665
Reputation: 5929
Your test cases should not depends on data created by another test cases. All your test have to be able to work in isolation.
As you're using DatabaseCleaner
you have to bootstrap all needed data for particular test.
Usually it can be described using before
block or let
.
So in your case you have to create Block
instance using factory_girl (in case you're using it) or as usual:
FactoryGirl.create :block, canvas_id: 1, case_id: 1
# or
Block.create canvas_id: 1, case_id: 1
hint: For Capybara 2.x there is aliases for methods:
before
=> background
let
=> given
Upvotes: 2
Reputation: 13037
Your problem may be related with the fact that the tests are being wrapped in database transactions, so any process runing outside of it (like selenium) does not see it. You should configure your js
tests to be cleaned by a truncation strategy:
First, if you use ActiveRecord, set:
config.use_transactional_fixtures = false
And the configure like following (basically, setting :transaction
strategy when possible, and using :truncation
only for :js
tests):
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, :js => true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
This is taken from (and you can see more information in there):
Upvotes: 1