Last active
December 29, 2015 12:59
-
-
Save ichilton/7674331 to your computer and use it in GitHub Desktop.
rspec ordering problem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This doesn't seem to work because the before(:each) is not called before the inner before(:all) is run... | |
context "when updating" do | |
before(:each) { @bible = create(:bible, code: 'OLD_CODE', alias: 'OLD_ALIAS') } | |
context "when not updating alias" do | |
before(:all) do | |
@bible.update_attributes(name: 'Different Name', code: 'UPDATED') | |
end | |
it "should have the updated title" do | |
expect(@bible.name).to eq 'Different Name' | |
end | |
it "should have the updated code" do | |
expect(@bible.code).to eq 'UPDATED' | |
end | |
it "should have the old alias" do | |
expect(@bible.alias).to eq 'OLD_ALIAS' | |
end | |
end | |
context "when updating alias" do | |
before(:all) do | |
bible.update_attributes(name: 'Different Name', code: 'UPDATED', alias: 'NEW_ALIAS') | |
end | |
it "should have the updated title" do | |
expect(bible.name).to eq 'Different Name' | |
end | |
it "should have the updated code" do | |
expect(bible.code).to eq 'UPDATED' | |
end | |
it "should have the old alias" do | |
expect(bible.alias).to eq 'NEW_ALIAS' | |
end | |
end | |
context "when updating alias to nil" do | |
before(:all) do | |
bible.update_attributes(name: 'Different Name', code: 'UPDATED', alias: nil) | |
end | |
it "should have the updated title" do | |
expect(bible.name).to eq 'Different Name' | |
end | |
it "should have the updated code" do | |
expect(bible.code).to eq 'UPDATED' | |
end | |
it "should have the correct alias (same as code)" do | |
expect(bible.alias).to eq 'UPDATED' | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Changing the before(:each) to let becomes: | |
context "when updating" do | |
let(:bible) { create(:bible, code: 'OLD_CODE', alias: 'OLD_ALIAS') } | |
context "when not updating alias" do | |
before(:all) do | |
bible.update_attributes(name: 'Different Name', code: 'UPDATED') | |
end | |
it "should have the updated title" do | |
expect(bible.name).to eq 'Different Name' | |
end | |
it "should have the updated code" do | |
expect(bible.code).to eq 'UPDATED' | |
end | |
it "should have the old alias" do | |
expect(bible.alias).to eq 'OLD_ALIAS' | |
end | |
end | |
context "when updating alias" do | |
before(:all) do | |
bible.update_attributes(name: 'Different Name', code: 'UPDATED', alias: 'NEW_ALIAS') | |
end | |
it "should have the updated title" do | |
expect(bible.name).to eq 'Different Name' | |
end | |
it "should have the updated code" do | |
expect(bible.code).to eq 'UPDATED' | |
end | |
it "should have the old alias" do | |
expect(bible.alias).to eq 'NEW_ALIAS' | |
end | |
end | |
context "when updating alias to nil" do | |
before(:all) do | |
bible.update_attributes(name: 'Different Name', code: 'UPDATED', alias: nil) | |
end | |
it "should have the updated title" do | |
expect(bible.name).to eq 'Different Name' | |
end | |
it "should have the updated code" do | |
expect(bible.code).to eq 'UPDATED' | |
end | |
it "should have the correct alias (same as code)" do | |
expect(bible.alias).to eq 'UPDATED' | |
end | |
end | |
end | |
# But this gives: | |
WARNING: let declaration `bible` accessed in a `before(:all)` hook at: | |
/vagrant/myproj_v2/spec/models/bible_spec.rb:140:in `block (5 levels) in <top (required)>' | |
This is deprecated behavior that will not be supported in RSpec 3. | |
`let` and `subject` declarations are not intended to be called | |
in a `before(:all)` hook, as they exist to define state that | |
is reset between each example, while `before(:all)` exists to | |
define state that is shared across examples in an example group. | |
I've got it working like this, but it's inefficient because of the creating and destroying for each assertion :( - is there a neater way?
describe "alias behaviour" do
context "when alias is provided" do
before(:all) { @bible = create(:bible, code: 'CODE', alias: 'ALIAS') }
it "should use the provided alias" do
expect(@bible.alias).to eq 'ALIAS'
end
it "should have the correct code" do
expect(@bible.code).to eq 'CODE'
end
it "should not have the same code and alias" do
expect(@bible.alias).not_to eq @bible.code
end
end
context "when alias is not provided" do
before(:all) { @bible = create(:bible, code: 'FRED', alias: nil) }
it "should have the correct alias" do
expect(@bible.alias).to eq 'FRED'
end
it "should have the same code and alias" do
expect(@bible.alias).to eq @bible.code
end
end
context "when updating" do
before(:each) { @bible = create(:bible, code: 'OLD_CODE', alias: 'OLD_ALIAS') }
after(:each) { @bible.destroy }
context "when not updating alias" do
before(:each) { @bible.update_attributes(name: 'Different Name', code: 'UPDATED') }
it "should have the updated title" do
expect(@bible.name).to eq 'Different Name'
end
it "should have the updated code" do
expect(@bible.code).to eq 'UPDATED'
end
it "should have the old alias" do
expect(@bible.alias).to eq 'OLD_ALIAS'
end
end
context "when updating alias" do
before(:each) { @bible.update_attributes(name: 'Different Name', code: 'UPDATED', alias: 'NEW_ALIAS') }
it "should have the updated title" do
expect(@bible.name).to eq 'Different Name'
end
it "should have the updated code" do
expect(@bible.code).to eq 'UPDATED'
end
it "should have the old alias" do
expect(@bible.alias).to eq 'NEW_ALIAS'
end
end
context "when updating alias to nil" do
before(:each) { @bible.update_attributes(name: 'Different Name', code: 'UPDATED', alias: nil) }
it "should have the updated title" do
expect(@bible.name).to eq 'Different Name'
end
it "should have the updated code" do
expect(@bible.code).to eq 'UPDATED'
end
it "should have the correct alias (same as code)" do
expect(@bible.alias).to eq 'UPDATED'
end
end
end
end
Not quite as DRY, but I think this is neater....
describe "alias behaviour" do
context "when alias is provided" do
before(:all) { @bible = create(:bible, code: 'CODE', alias: 'ALIAS') }
it "should use the provided alias" do
expect(@bible.alias).to eq 'ALIAS'
end
it "should have the correct code" do
expect(@bible.code).to eq 'CODE'
end
it "should not have the same code and alias" do
expect(@bible.alias).not_to eq @bible.code
end
end
context "when alias is not provided" do
before(:all) { @bible = create(:bible, code: 'FRED', alias: nil) }
it "should have the correct alias" do
expect(@bible.alias).to eq 'FRED'
end
it "should have the same code and alias" do
expect(@bible.alias).to eq @bible.code
end
end
context "when updating" do
context "when not updating alias" do
before(:all) do
@bible = create(:bible, code: 'OLD_CODE', alias: 'OLD_ALIAS')
@bible.update_attributes(name: 'Different Name', code: 'UPDATED')
end
after(:all) { @bible.destroy}
it "should have the updated title" do
expect(@bible.name).to eq 'Different Name'
end
it "should have the updated code" do
expect(@bible.code).to eq 'UPDATED'
end
it "should have the old alias" do
expect(@bible.alias).to eq 'OLD_ALIAS'
end
end
context "when updating alias" do
before(:all) do
@bible = create(:bible, code: 'AN_OLD_CODE', alias: 'AN_OLD_ALIAS')
@bible.update_attributes(name: 'A Different Name', code: 'AN_UPDATED_CODE', alias: 'NEW_ALIAS')
end
it "should have the updated title" do
expect(@bible.name).to eq 'A Different Name'
end
it "should have the updated code" do
expect(@bible.code).to eq 'AN_UPDATED_CODE'
end
it "should have the old alias" do
expect(@bible.alias).to eq 'NEW_ALIAS'
end
end
context "when updating alias to nil" do
before(:all) do
@bible = create(:bible, code: 'ANOTHER_OLD_CODE', alias: 'ANOTHER_OLD_ALIAS')
@bible.update_attributes(name: 'Another Different Name', code: 'ANOTHER_UPDATED_CODE', alias: nil)
end
it "should have the updated title" do
expect(@bible.name).to eq 'Another Different Name'
end
it "should have the updated code" do
expect(@bible.code).to eq 'ANOTHER_UPDATED_CODE'
end
it "should have the correct alias (same as code)" do
expect(@bible.alias).to eq 'ANOTHER_UPDATED_CODE'
end
end
end
end
Let me blow your mind:
describe "alias behaviour" do
context "with alias" do
subject { create(:bible, code: 'CODE', alias: 'ALIAS') }
its(:alias) { should eq 'ALIAS' }
its(:code) { should eq 'CODE' }
its(:alias) { should_not eq subject.code }
end
context "when alias is not provided" do
subject { create(:bible, code 'FRED', alias: nil) }
its(:alias) { should eq 'FRED' }
its(:alias) { should eq subject.code }
end
context "when updating" do
context "when not updating alias" do
subject { create(:bible, code: 'OLD_CODE', alias: 'OLD_ALIAS') }
before(:all) { subject.update_attributes(name: 'Different Name', code: 'UPDATED') }
after(:all) { subject.destroy}
its(:name) { should eq 'Different Name' }
its(:code) { should eq 'UPDATED' }
its(:alias) { should eq 'OLD_ALIAS' }
end
end
⋮
end
Thanks Philip.
That does look a lot neater/shorter, but the problem with subject is it works like before(:each) and let in that it runs for each test - that's why i've started doing things like:
before(:all) { @something = create(:something) }
subject { @something }
The shorthand its syntax does look better in the specs, but does make the output a bit ambiguous as all you see is the test data, so I tend to use that more for things like be_valid....
Thanks,
Ian
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
What's the correct way to do this?
I want to have a record which is created for each context, and each context to have an update that is performed once for that context...