[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

MiniTest: a curious case of include (1.8 vs 1.9

bahuvrihi

1/29/2009 3:13:00 PM

I've been messing around with minitest and came across something very
strange. Does anyone have an explanation for what is going on here?
I think it must indicate subtle differences in blocks between 1.8 and
1.9.

require 'rubygems'
require 'minitest/spec'

#
# Including a module in a spec does not make constants
# available under ruby 1.8 but it does under ruby 1.9.
#
# This script requires the minitest gem to be installed:
#
# % gem install minitest
#

module A
module B
end
end

# This passes on ruby 1.9, but not on 1.8.
describe "MiniTest Includes" do
include A

it "should show inclusion works" do
B.must_equal A::B
end
end

# This passes on both. What's more, if you uncomment this
# spec, the assignment TRANSLATES to the "MiniTest Includes"
# spec and that spec will pass!
#
# describe "MiniTest Assigns" do
# B = A::B
#
# it "should show assignment works" do
# B.must_equal A::B
# end
# end

# Here is an example showing the assignment case works.
module X
module Y
end
end

describe "MiniTest Assigns X::Y" do
Y = X::Y

it "should show constant assignment works" do
Y.must_equal X::Y
end
end

MiniTest::Unit.autorun

6 Answers

bahuvrihi

1/29/2009 4:05:00 PM

0

As an additional note to this, assigning constants in a describe under
1.8 causes namespace pollution.

require 'rubygems'
require 'minitest/spec'

module X
module Y
end
end

describe "Namespace Pollution" do
Y = X::Y
end

puts Y # => 'X::Y' on 1.8, error on 1.9

David A. Black

1/29/2009 4:21:00 PM

0

Hi --

On Fri, 30 Jan 2009, Simon Chiang wrote:

> As an additional note to this, assigning constants in a describe under
> 1.8 causes namespace pollution.
>
> require 'rubygems'
> require 'minitest/spec'
>
> module X
> module Y
> end
> end
>
> describe "Namespace Pollution" do
> Y = X::Y
> end
>
> puts Y # => 'X::Y' on 1.8, error on 1.9

It's not specific to minitest; it's a change in how constants are
resolved. I'm not sure of the exact formulation but what's happening
is that in a class_eval'd code block (which I think is what describe
does), 1.8 is looking for a constant scoped to the outer level, while
1.9 is looking for one that is scope to the class that's being
class_evaled.

You can see this also with a block for a new class:

module A
module B
end
end

Class.new do
include A
p B == A::B # true in 1.9, error in 1.8 (unknown constant B)
end


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

http://www.wis... => Independent, social wishlist management!

bahuvrihi

1/29/2009 6:51:00 PM

0


> It's not specific to minitest; it's a change in how constants are
> resolved. I'm not sure of the exact formulation but what's happening
> is that in a class_eval'd code block (which I think is what describe
> does), 1.8 is looking for a constant scoped to the outer level, while
> 1.9 is looking for one that is scope to the class that's being
> class_evaled.

Interesting. I expected it would be something like this. Kinda makes
specs hard to use under 1.8 IMO. You're left with nesting describes
within a module, or using the full constant name.

module A
module B
end

describe "Nest in Module" do
it "should show nesting works" do
B.must_equal A::B
end
end
end

describe "Full Constant Name" do
it "should show full names works" do
A::B.must_equal A::B
end
end

David A. Black

1/29/2009 8:37:00 PM

0

Hi --

On Fri, 30 Jan 2009, Simon Chiang wrote:

>
>> It's not specific to minitest; it's a change in how constants are
>> resolved. I'm not sure of the exact formulation but what's happening
>> is that in a class_eval'd code block (which I think is what describe
>> does), 1.8 is looking for a constant scoped to the outer level, while
>> 1.9 is looking for one that is scope to the class that's being
>> class_evaled.
>
> Interesting. I expected it would be something like this. Kinda makes
> specs hard to use under 1.8 IMO. You're left with nesting describes
> within a module, or using the full constant name.
>
> module A
> module B
> end
>
> describe "Nest in Module" do
> it "should show nesting works" do
> B.must_equal A::B
> end
> end
> end
>
> describe "Full Constant Name" do
> it "should show full names works" do
> A::B.must_equal A::B
> end
> end

All it means is that you can't make an assertion in the spec that
conflicts with how the language is engineered, and that's always true
:-)


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

http://www.wis... => Independent, social wishlist management!

bahuvrihi

1/30/2009 5:52:00 PM

0


> All it means is that you can't make an assertion in the spec that
> conflicts with how the language is engineered, and that's always true
> :-)

I guess there's something to that. Here's a good workaround that
doesn't pollute and works on 1.8 and 1.9... evade the block by
foregoing describe.

module A
module B
end
end

# This passes on both ruby 1.8 and 1.9 and doesn't pollute.
class MiniTestIncludes < MiniTest::Spec
include A

it "should show inclusion works" do
B.must_equal A::B
end
end

bwv549

2/2/2009 8:01:00 PM

0

Here's a workaround that combines the include call with a const_get
call. Can still use 'describe'. Doesn't pollute namespace. Works on
1.8 and 1.9. Not too ugly:

require 'minitest/spec'
MiniTest::Unit.autorun

# put this little method in some kind of spec_helper.rb file
module Kernel
def use(const, subconst)
self.instance_eval( "include #{const}" )
const.const_get(subconst)
end
end

module A
module B
end
end

describe 'Includes' do
B = use A, 'B'

it 'shows inclusion working' do
B.must_equal A::B
end
end