tomykaira / rspec-parameterized

RSpec::Parameterized supports simple parameterized test syntax in rspec.
MIT License
417 stars 28 forks source link

When use let method in where scope, scope of evaluation is different with actual ExampleGroup #8

Open joker1007 opened 12 years ago

joker1007 commented 12 years ago

Primitive values is basically No Problem. But side-effective method is not equivalent to with_them, because with_them create another ExampleGroup instance. (ex. FactoryGirl.create)

I think that to solve this issue, we need to hook rspec-core, but it is difficult.

proc & instance_eval hack is still necessary.

tomykaira commented 12 years ago

Thank you for pointing out. Hmm, that's a problem.

As I wrote in my blog post, basically I expect simple values as input. Procs, stateful objects, etc. are out of my scope.

Of course, however, it is great if this library can handle such complex cases. I will try it when I have time.

rroger commented 6 years ago

It would be great when this issue could be addressed, because I can not use something like:

describe '#execute' do
  let!(:private_group)  { create(:group, :private) }
  let!(:internal_group) { create(:group, :internal) }
  let!(:public_group)   { create(:group, :public) }

  let!(:user_private_group)  { create(:group, :private) }
  let!(:user_internal_group) { create(:group, :internal) }
  let!(:user_public_group)   { create(:group, :public) }

  describe 'root level groups' do
    using RSpec::Parameterized::TableSyntax

    where(:user, :params, :results) do
      nil | { all_available: true  } | [public_group, user_public_group]
      nil | { all_available: false  } | [public_group, user_public_group]
      nil | {} | [public_group, user_public_group]
    end

    with_them do
      before do
        if user
          [user_private_group, user_internal_group, user_public_group].each { |group| group.add_developer(user) }
        end
      end

    subject { described_class.new(user, params).execute.to_a }
      it { is_expected.to match_array(results) }
    end
  end
end

because it uses different groups in the expectation than in the actual result. If I print all available groups in the test it self, I get:

{:all_available=>false}
[{:id=>18, :type=>20},
 {:id=>17, :type=>10},
 {:id=>16, :type=>0},
 {:id=>15, :type=>20},
 {:id=>14, :type=>10},
 {:id=>13, :type=>0}]

expected collection contained:  [#<Group id:21 @group3>, #<Group id:22 @group4>]
actual collection contained:    [#<Group id:15 @group21>, #<Group id:18 @group24>]
the missing elements were:      [#<Group id:21 @group3>, #<Group id:22 @group4>]
the extra elements were: :        [#<Group id:15 @group21>, #<Group id:18 @group24>]

So the tests expects groups with id 21, but all groups that are in the test have an id < 18.

another thing is, that if I try to define the groups in the same describe block as the parameterized test, I get an

An error occurred while loading ./spec/finders/groups_finder_spec.rb.
   Failure/Error: nil | { all_available: true  } | [public_group, user_public_group]

   NoMethodError:
   super: no superclass method `public_group' for #<RSpec::ExampleGroups::Gr     oupsFinder::Execute::RootLevelGroups:0x00007fdc0322b8e8>
   Did you mean?  public_method