I just started enabling @javascript on some cucumber scenarios and I am having some lack of understanding as to what is going on with data which should be seeded in the db:
In env.rb I have:
AfterConfiguration do |config|
Factory.create(:sysadmin_role)
Factory.create(:practice_admin_role)
Factory.create(:practice_user_role)
end
So that I have necessary roles to create users.
When a scenario with @javascript runs, I get the following error, which relates to the fact that the role that is being sought does not exist:
-10-07 20:22:29] ERROR RuntimeError: Called id for nil, which would mistakenly be 4 – if you really wanted the id of nil, use object_id
/Users/DK/Documents/ror/projects/wavelineup3/app/controllers/practices_controller.rb:38:in `create’
And when I check on the db, my factories are not there, i.e. Role.all = .
I have tried everything including creating the data directly in the associated step itself and to no avail. Any advice? I am going to be doing a lot of ajax/js testing, should I ditch Capybara in favor of Selenium?
I just started enabling @javascript on some cucumber scenarios and I am
having some lack of understanding as to what is going on with data which
should be seeded in the db:
Nothing should ever be seeded in the DB in testing. You want a clean
slate. Set up only the records you need for each scenario.
Nothing should ever be seeded in the DB in testing. You want a clean
slate. Set up only the records you need for each scenario.
Right - maybe I am missing something, how do you add records before a scenario? Is there a before(:each) like in rspec?
Also, I just changed my env.rb to culerity which I overlooked:
Capybara.javascript_driver = :culerity #default driver when you using @javascript tag
I now see this error on a lot of tests - have you seen this? I did not exhaustively google but does not seem to be any clear and easy resolution:
Broken pipe (Errno::EPIPE)
Nothing should ever be seeded in the DB in testing. You want a clean
slate. Set up only the records you need for each scenario.
THIS
if you need your scenario to have some context use background: like this
Background:
Given a thug exist with name: “juan”
And a car exist with owner: “jonny”
Scenario: can steal car
Given “juan” is near the car
When “juan” opens it
Then I should not see the police
Scenario: get busted
Given “juan” stole the car
When “jonny” calls the police
Then I should see “juan” get arrested
this way jaun and jonny exist for both scenarios and the their are created for each feature.
also i like using selenium-webdriver to test javascript if i see something wrong in the first pass.
Thanks Marnen and Radhames for the help… got things working. Radhames, took your lead and tried the selenium driver instead of culerity.
I think there is some issue with culerity on Rails 3/1.9.2 (a broken pipe error occurs regularly) but w selenium things went smooth. You probably already know this but for completeness of this post, I actually found while looking at Scenario Backgrounds the cucumber hooks for running something before each scenario in the whole suite (below)… in this case the user roles always have to be there so it makes more sense to put this there than inside each feature.
env.rb
Before do
Factory.create(:sysadmin_role)
Factory.create(:practice_admin_role)
Factory.create(:practice_user_role)
end
Thanks Marnen and Radhames for the help... got things working. Radhames,
took your lead and tried the selenium driver instead of culerity.
I think there is some issue with culerity on Rails 3/1.9.2 (a broken
pipe
error occurs regularly) but w selenium things went smooth. You probably
already know this but for completeness of this post, I actually found
while
looking at Scenario Backgrounds the cucumber hooks for running something
before each scenario in the whole suite (below)... in this case the user
roles always have to be there so it makes more sense to put this there
than
inside each feature.
No, no, no, it really doesn't. Do you actually touch all three of those
roles for every single Cucumber scenario? (I'll bet you don't.) If you
don't, then you're just making extra records and confusing what you're
testing. The Before block is not the place to create records.
env.rb
Before do
Factory.create(:sysadmin_role)
Factory.create(:practice_admin_role)
Factory.create(:practice_user_role)
end
No, no, no, it really doesn’t. Do you actually touch all three of those
roles for every single Cucumber scenario? (I’ll bet you don’t.) If you
don’t, then you’re just making extra records and confusing what you’re
testing. The Before block is not the place to create records.
Its a grey area, as user roles a a presupposition of the system, and probably 90%+ of all tests would fail without them — and they are far from my mind when writing scenarios. I could put them instead in the step which creates any user, but that is less pretty as I might create several users throughout a single scenario. They are the only seed data that would go into the production database.
Originally I added them in env.rb using the following which would add them once:
AfterConfiguration do |config|
Factory.create(:sysadmin_role)
Factory.create(:practice_admin_role)
Factory.create(:practice_user_role)
end
But with the @javascript tests they were not loading (or were getting deleted).
David Kahn wrote:
[The following paragraph was me. Please quote properly.]
No, no, no, it really doesn't. Do you actually touch all three of those
roles for every single Cucumber scenario? (I'll bet you don't.) If you
don't, then you're just making extra records and confusing what you're
testing. The Before block is not the place to create records.
[And back to you...]
Its a grey area, as user roles a a presupposition of the system, and
probably 90%+ of all tests would fail without them --- and they are far
from
my mind when writing scenarios.
They should not be far from your mind! You should set them up in every
test and scenario for which you need them, so that you know exactly
which features depend on them.
I could put them instead in the step
which
creates any user, but that is less pretty as I might create several
users
throughout a single scenario.
That's OK. Create the users with appropriate roles as you need them
(Pickle can really help here).
They are the only seed data that would go
into
the production database.
Fine, then seed the production database. Never seed the test database.
Originally I added them in env.rb using the following which would add
them
once:
AfterConfiguration do |config|
Factory.create(:sysadmin_role)
Factory.create(:practice_admin_role)
Factory.create(:practice_user_role)
end
I know. That's bad practice, as I've been explaining.
But with the @javascript tests they were not loading (or were getting
deleted).
So take the time now to drop the bad practice and do it right!
They should not be far from your mind! You should set them up in every
test and scenario for which you need them, so that you know exactly
which features depend on them.
So take the time now to drop the bad practice and do it right!
I see the point and trying to swallow it. That’s going to make me think a bit differently but I can see the benefit. Although, this also makes me think that doing associations or the like within factories according to your logic would also be bad practice, right? I mean, that is also data which is implied.
They should not be far from your mind! You should set them up in every
test and scenario for which you need them, so that you know exactly
which features depend on them.
So take the time now to drop the bad practice and do it right!
[Still not quoting properly. That was me.]
I see the point and trying to swallow it. That's going to make me think
a
bit differently but I can see the benefit. Although, this also makes me
think that doing associations or the like within factories according to
your
logic would also be bad practice, right?
No. Part of the reason we use factories is so we can produce, on the
fly, a usable record with all associations and validations satisfied.
I mean, that is also data which
is
implied.
Huh? You mean in the sense that you didn't explicitly create the
associated records? That's OK, because you're still creating them *for
the particular test*.
See, your test DB should start out every scenario or test completely
empty, and only create the records needed for that particular test. If
(say) Factory :event also creates a User record for the Event to belong
to, that's fine -- an Event (in this example) can't exist without an
owning User, so we need the User in order to test the Event. We are
creating all necessary records, but only the necessary records.
See, your test DB should start out every scenario or test completely
empty, and only create the records needed for that particular test. If
(say) Factory :event also creates a User record for the Event to belong
to, that’s fine – an Event (in this example) can’t exist without an
owning User, so we need the User in order to test the Event. We are
creating all necessary records, but only the necessary records.
Right, I fully agree with this. So either I should create the roles in this case before each test or let the factories create, either way there is a clean slate.
See, your test DB should start out every scenario or test completely
empty, and only create the records needed for that particular test. If
(say) Factory :event also creates a User record for the Event to belong
to, that's fine -- an Event (in this example) can't exist without an
owning User, so we need the User in order to test the Event. We are
creating all necessary records, but only the necessary records.
For the third time: fix your quoting!
Right, I fully agree with this. So either I should create the roles in
this
case before each test or let the factories create, either way there is a
clean slate.
But your Before block is not creating *only* the necessary records for
each test. That's why you shouldn't be using it.