Forum: RSpec dynamic tests possible?

Posted by Roger Pack (rogerdpack)
on 2010-08-18 18:31
(Received via mailing list)
Sorry if this is a newbie question, but here goes.

I was wondering if the following is somehow possible:


  for file in Dir['*.bmp']
    it "should be able to parse #{file}" do
      p file
      # test this file
    end
  end

Currently rspec seems to evaluate the blocks after the fact, leading
to "file" always being the last file in the list.
I was unsure how to pass a parameter into an "it" block.
Thoughts?
Thanks.
-r
Posted by David Chelimsky (Guest)
on 2010-08-18 18:41
(Received via mailing list)
On Aug 18, 2010, at 11:31 AM, rogerdpack wrote:

> Sorry if this is a newbie question, but here goes.
> 
> I was wondering if the following is somehow possible:
> 
> 
>  for file in Dir['*.bmp']

Use this instead:

Dir["*.bmp"].each do |file|
Posted by David Chelimsky (Guest)
on 2010-08-18 19:34
(Received via mailing list)
On Aug 18, 2010, at 11:38 AM, David Chelimsky wrote:

> Use this instead:
> 
> Dir["*.bmp"].each do |file| 
>>   it "should be able to parse #{file}" do
>>     p file
>>     # test this file
>>   end
>> end

The reason, btw, has to do with ruby closures and scope. Ruby blocks are 
closures, which means they have access to the state of the scope in 
which they were defined, but they don't access that state until they are 
evaluated. By using an iterator that takes a block, we end up with two 
nested closures:

[1,2,3].each do |n|
  it "is #{n}" do
    puts n
  end
end

Here, the first time through the outer iterator, the value of n is 1. 
The string passed to it() is evaluated at this time, so that string is 
transformed to "is 1". The block passed to it() is not eval'd yet, but 
when it does get evaluated it will take on the value of the scope in 
which it was defined, which the block passed to the iterator with its 
block parameter. This will maintain a value of 1.

for n in [1,2,3]
  it "is #{n}" do
    puts n
  end
end

Here, the first time through the outer loop, the value of n is 1. Again, 
the string passed to it() is evaluated at this time, so that string is 
transformed to "is 1".  When the block is eval'd, the scope in which it 
was defined is the same scope in which the loop was defined, so n will 
have changed to the last item in the list, 3.

Does this make sense to you?

Cheers,
David
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.