Hello everyone,

firstly I'm sorry for my poor english, I hope I'll manage to be clear; 
don't hesitate to ask for clarifications if I will not.

In my tests this is a common pattern:

describe Hello do
  def a
    @a ||= 'a'
  end

  def b
    @b ||= 'b'
  end

  def c
    @c ||= 'c'
  end

  let(:d) { 'd' }
  let(:e) { 'e' }
  let(:f) { 'f' }

  before(:all) do
    a
    b
    c
  end
end

I have to use def ... for the methods used inside before(:all), due to the 
problems described in https://github.com/rspec/rspec-core/issues/500 .

My problem with it is that I don't like its readability: it isn't DRY and 
it doesn't express what I intend.

My ideal pattern would be like this:

describe Hello do
  let(:a) { 'a' }
  let(:b) { 'b' }
  let(:c) { 'c' }
  let(:d) { 'd' }
  let(:e) { 'e' }
  let(:f) { 'f' }

  before(:all) do
    a
    b
    c
  end
end

But I know it is utopian, since the problem described in the issue above.

So I would like to have your opinions about something like (notice set 
instead of let):

describe Hello do
  set(:a) { 'a' }
  set(:b) { 'b' }
  set(:c) { 'c' }
  let(:d) { 'd' }
  let(:e) { 'e' }
  let(:f) { 'f' }

  before(:all) do
    a
    b
    c
  end
end

Or (maybe even better) something like:

describe Hello do
  let(:a, :all) { 'a' }
  let(:b, :all) { 'b' }
  let(:c, :all) { 'c' }
  let(:d) { 'd' }
  let(:e) { 'e' }
  let(:f) { 'f' }

  before(:all) do
    a
    b
    c
  end
end

I think it is better with "let, argument indicating using in before(:all)" 
because it is unnecessary to create another method, and it is more 
"explicit" about what it's doing.

At the moment, I'm using the following (as poor as effective) 
implementation:

module RSpecSet
  def set(name, &block)
    instance_variable_name = :"@#{name}"

    define_method(name) do
      return instance_variable_get instance_variable_name if 
instance_variable_defined? instance_variable_name
      
      instance_variable_set instance_variable_name, block.call
    end
  end

  def set!(name, &block)
    define_method(name) { instance_variable_set :"@#{name}", block.call }
  end
end

Rspec.config { |c| c.extend RSpecSet }

Where set memoizes the result into an instance variable, while set! does 
not.

Looking at rspec-core-3.0.0.beta2/lib/rspec/core/memoized_helpers.rb , 
where let and let! are implemented, I guess that an implementation more 
similar to it would be more appropriate, but I haven't figured out it yet.

What do you think about it? Am I the only with this need? Are you happy 
with the "if not in before_all let else def" approach? Do you have ideas in 
order to improve my RSpecSet?

Thank you all and long live to RSpec :)

-- 
You received this message because you are subscribed to the Google Groups 
"rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rspec/f9905aa6-e11b-4215-9969-8eab8b88ac62%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to