Permalink
Browse files

Added a test for Array#flatten that passes in 1.8.7, but fails in 1.9…

….2 to demonstrate a change in behaviour between the two versions :-

    Array#flatten does not call to_ary on an elements if element does not respond to to_ary FAILED
    Expected to not get NotNoMethodError

I'd like to confirm whether this change in behaviour is intentional.

See [this Ruby mailing list thread](http://www.ruby-forum.com/topic/450307) and [this Mocha ticket](http://floehopper.lighthouseapp.com/projects/22289/tickets/70) for more details.
  • Loading branch information...
floehopper committed Nov 18, 2010
1 parent 7dbeac1 commit 3d8edf7d24899a005e3cd40867394e29761f68a8
Showing with 13 additions and 0 deletions.
  1. +13 −0 core/array/flatten_spec.rb
View
@@ -98,6 +98,19 @@
lambda { [obj].flatten.should == [obj] }.should_not raise_error(NoMethodError)
end
it "does not call to_ary on an elements if element does not respond to to_ary" do
NotNoMethodError = Class.new(StandardError)
obj = Class.new do
def method_missing(symbol, *args, &block)
symbol == :to_ary ? raise(NotNoMethodError) : super
end
def respond_to?(symbol, include_private = false)
symbol == :to_ary ? false : super
end
end.new
lambda { [obj].flatten.should == [obj] }.should_not raise_error(NotNoMethodError)
end
it "ignores the return value of to_ary if it is nil" do
obj = Class.new do
def to_ary

2 comments on commit 3d8edf7

@marcandre

This comment has been minimized.

Show comment
Hide comment
@marcandre

marcandre Nov 18, 2010

Firstly, defining respond_to? here has no effect, since Object does not respond to to_ary.

Secondly, the test doesn't really show that method_missing isn't called (contrary to the label of the test); all exceptions could be rescued by flatten and the test would still pass.

Finally, I believe the change was done by Matz in r25556, see [ruby-core:23738].

marcandre replied Nov 18, 2010

Firstly, defining respond_to? here has no effect, since Object does not respond to to_ary.

Secondly, the test doesn't really show that method_missing isn't called (contrary to the label of the test); all exceptions could be rescued by flatten and the test would still pass.

Finally, I believe the change was done by Matz in r25556, see [ruby-core:23738].

@floehopper

This comment has been minimized.

Show comment
Hide comment
@floehopper

floehopper Nov 18, 2010

Member

You are correct when you say that defining respond_to? has no effect in the test i.e. an instance of Object does not respond_to? #to_ary by default. However, I wanted to be explicit to make the test clearer.

The test label says to_ary is not called; it does not say method_missing is not called. Having Array#flatten rescue all exceptions would indeed pass the test, but would not be desirable behaviour. I had a different version of the test that called flunk in method_missing, perhaps that would be better. Alternatively it might be better to try and use some type of mock object to check #to_ary is not called when #respond_to? returns false for :to_ary.

In any case, I'm sure the test could be better written. My main aim was to understand why the behaviour had changed between 1.8.7 & 1.9.2. Your reference looks like it might give me the answer, but I can't access the Ruby ticketing system at the moment. Thanks.

Member

floehopper replied Nov 18, 2010

You are correct when you say that defining respond_to? has no effect in the test i.e. an instance of Object does not respond_to? #to_ary by default. However, I wanted to be explicit to make the test clearer.

The test label says to_ary is not called; it does not say method_missing is not called. Having Array#flatten rescue all exceptions would indeed pass the test, but would not be desirable behaviour. I had a different version of the test that called flunk in method_missing, perhaps that would be better. Alternatively it might be better to try and use some type of mock object to check #to_ary is not called when #respond_to? returns false for :to_ary.

In any case, I'm sure the test could be better written. My main aim was to understand why the behaviour had changed between 1.8.7 & 1.9.2. Your reference looks like it might give me the answer, but I can't access the Ruby ticketing system at the moment. Thanks.

Please sign in to comment.