before block running for each example - How can I improve it ?

105 views
Skip to first unread message

Arup Rakshit

unread,
Jun 13, 2014, 9:22:09 AM6/13/14
to rs...@googlegroups.com
I have the below method

  def fetch_starred_posts(page, per)
    favorites_post_ids = self.favorites.pluck(:favoriteable_id)
    Post.where(id: favorites_post_ids).order("created_at desc").page(page || 1).per(per) 
  end


The TDD for the above code is

  describe "#fetch_starred_posts" do
    let(:user1) { FactoryGirl.create(:user) }
    let(:user2) { FactoryGirl.create(:user) }
    let!(:post1) { FactoryGirl.create(:post) }
    let!(:post2) { FactoryGirl.create(:post) }

    context "when user starred 1 post out of 2 posts " do
      before do
        user1.favorites.create(favoriteable_id: post1.id, favoriteable_type: "Post")
        user2.favorites.create(favoriteable_id: post2.id, favoriteable_type: "Post")
      end

      it "should include post1 in user1's starred posts list, but not post2 " do
        expect(user1.fetch_starred_posts(1,2)).to include(post1)
        expect(user1.fetch_starred_posts(1,2)).not_to include(post2)
      end

      it "should include post2 in user2's starred posts list, but not post1  " do
        expect(user2.fetch_starred_posts(1,2)).to include(post2)
        expect(user2.fetch_starred_posts(1,2)).not_to include(post1)
      end
    end

    context "when pagination is used" do
      before do
        user1.favorites.create(favoriteable_id: post1.id, favoriteable_type: "Post")
        user1.favorites.create(favoriteable_id: post2.id, favoriteable_type: "Post")
      end

      it "should return only one starred post in first page" do
        page, per = 1, 1
        starred_posts = user1.fetch_starred_posts(page, per)
        expect(starred_posts.count).to eq(1)
        expect(starred_posts).to include(post2)
      end

      it "should return only one starred post in first page" do
        page, per = 2, 1
        starred_posts = user1.fetch_starred_posts(page, per)
        expect(starred_posts.count).to eq(1)
        expect(starred_posts).to include(post1)
      end

    end

  end


The Rspec is running perfectly. But in the *pagination* part the *before* block running for each example, whereas it is not needed. Can I do execute the code once for both *it* examples not twice ?

Rob Park

unread,
Jun 13, 2014, 1:53:19 PM6/13/14
to rs...@googlegroups.com
As I understand it:

before(:all) runs the block one time before all of the examples are run.

before(:each) runs the block one time before each of your specs in the file


@robpark


Arup Rakshit

unread,
Jun 13, 2014, 2:43:18 PM6/13/14
to rs...@googlegroups.com

As I understand it:

before(:all) runs the block one time before all of the examples are run.

before(:each) runs the block one time before each of your specs in the file


@robpark

Yes, you understood it correctly. Pretty new I am. So don't have idea about "how to right Rspec more idiomatically". :) 

Thanks,
Arup

Arup Rakshit

unread,
Jun 16, 2014, 1:48:24 AM6/16/14
to rs...@googlegroups.com




As I understand it:

before(:all) runs the block one time before all of the examples are run.

before(:each) runs the block one time before each of your specs in the file


@robpark




But I got the below when I applied *:all*

Arup-iMac:yelloday shreyas$ rspec spec/models/post_spec.rb 
...WARNING: let declaration `user1` accessed in a `before(:all)` hook at:
  /Users/shreyas/yelloday/spec/models/post_spec.rb:881:in `block (4 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.
WARNING: let declaration `post1` accessed in a `before(:all)` hook at:
  /Users/shreyas/yelloday/spec/models/post_spec.rb:881:in `block (4 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.
WARNING: let declaration `user1` accessed in a `before(:all)` hook at:
  /Users/shreyas/yelloday/spec/models/post_spec.rb:882:in `block (4 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.
WARNING: let declaration `post2` accessed in a `before(:all)` hook at:
  /Users/shreyas/yelloday/spec/models/post_spec.rb:882:in `block (4 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.
...................................................................................................................

Finished in 16.27 seconds
118 examples, 0 failures
 

Rob Park

unread,
Jun 16, 2014, 6:44:31 AM6/16/14
to rs...@googlegroups.com
"let" isn't supported in before(:all) like it is in before(:each).
It doesn't really mean the same thing symantically at that point and AFAIK, you need to use @member vars to work around this.


@robpark

Reply all
Reply to author
Forward
0 new messages