Issues with the trunk of rspec-rails


#1

Hi folks,

I’m currently in the process of upgrading an old Rails project to the
Rails
2.2.2 and the trunk of RSpec, and ran into several issues with
rspec-rails.
I’ve come up with workarounds for all of them, but I wanted to report
them
to hopefully get them into better shape for other folks.

(1) config.include doesn’t work on controller, helper, or view specs if
no
:type parameter is required.

config.include sends an include to RailsExampleGroup. Unfortunately,
these
specs no longer extend RailsExampleGroup. Here’s my monkey patch:
module Spec
module Runner
class Configuration
def get_type_from_options(options)
options[:type] || options[:behaviour_type] || [:controller,
:model,
:view, :helper, nil]
end
end
end
end

(2) The render override for RSpec controllers only takes one argument.
This
means that any controller using two argument forms will fail.

Our biggest use case for the two-argument controller form is this:
render
:update, :status => 404 do {}
This case is still allowable and not deprecated in Rails 2.2.2.

(3) with_tag is completely broken, as it tries to use the outer class as
the
subject of ‘with_tag’, rather than the have_tag matcher that it lives
inside.

(4) assigns(:xxx) will give really bad errors if your class doesn’t
happen
to define == in such a way that it can equate to FalseClass.

Let me know if you’d like examples or extra explanation.
=N


#2

(3) with_tag is completely broken, as it tries to use the outer class as
the subject of ‘with_tag’, rather than the have_tag matcher that it lives
inside.

If you’re testing markup (view tests or whatever), take a look at my
elementor project[1]. I’ve found that it makes view testing a lot more
expressive, a lot less brittle, and a lot more fun! (Ok, maybe not the
last
bit). It also uses Nokogiri, so it’s much faster than have_tag.

  1. http://github.com/nakajima/elementor/tree/master

Pat


#3

On Tue, Feb 10, 2009 at 2:02 PM, Nathan W. removed_email_address@domain.invalid
wrote:

config.include sends an include to RailsExampleGroup. Unfortunately, these
specs no longer extend RailsExampleGroup.

What are they extending? Are they a custom class? You can resolve this
by making your custom class the default:

Spec::Example::ExampleGroupFactory.default(MyCustomBaseExampleGroupClass)

end

(2) The render override for RSpec controllers only takes one argument. This
means that any controller using two argument forms will fail.

Our biggest use case for the two-argument controller form is this: render
:update, :status => 404 do {}
This case is still allowable and not deprecated in Rails 2.2.2.

I can reinstate the extra arg. Are you looking for it to be handled in
some way? Or just to not blow up?

(3) with_tag is completely broken, as it tries to use the outer class as the
subject of ‘with_tag’, rather than the have_tag matcher that it lives
inside.

Was it working before and the upgrade broke existing specs? Or is this
a general observation?

(4) assigns(:xxx) will give really bad errors if your class doesn’t happen
to define == in such a way that it can equate to FalseClass.

Can you provide an example?

Let me know if you’d like examples or extra explanation.

Thanks for the insights thus far.

Cheers,
David


#4

On Tue, Feb 10, 2009 at 3:02 PM, Nathan W. removed_email_address@domain.invalid
wrote:

Hi folks,

I’m currently in the process of upgrading an old Rails project to the Rails
2.2.2 and the trunk of RSpec, and ran into several issues with rspec-rails.
I’ve come up with workarounds for all of them, but I wanted to report them
to hopefully get them into better shape for other folks.

(1) config.include doesn’t work on controller, helper, or view specs if no
:type parameter is required.

I ran into the same problem last night. Modules which I was
includning via “config.include…” were only available to my model
spec and not to my controller specs.

Thanks for tracking this down!


Josh K.
phone: 509-979-1593
email: removed_email_address@domain.invalid
web: http://joshknowles.com


#5

On Tue, Feb 10, 2009 at 10:49 PM, David C. removed_email_address@domain.invalid
wrote:

config.include sends an include to RailsExampleGroup. Unfortunately, these
specs no longer extend RailsExampleGroup.

What are they extending? Are they a custom class? You can resolve this
by making your custom class the default:

Spec::Example::ExampleGroupFactory.default(MyCustomBaseExampleGroupClass)

Nevermind that response - after discussing a bit with Zach D., he
straightened me out. Fix is in (along w/ specs, of course):

http://github.com/dchelimsky/rspec-rails/commit/872149262adbf911b6dd1f6c07805f4bdd3b5939


#6

Snipping down to relevant questions:

On Feb 10, 8:49 pm, David C. removed_email_address@domain.invalid wrote:

On Tue, Feb 10, 2009 at 2:02 PM, Nathan W. removed_email_address@domain.invalid wrote:

(2) The render override for RSpec controllers only takes one argument. This
means that any controller using two argument forms will fail.

Our biggest use case for the two-argument controller form is this: render
:update, :status => 404 do {}
This case is still allowable and not deprecated in Rails 2.2.2.

I can reinstate the extra arg. Are you looking for it to be handled in
some way? Or just to not blow up?

It shouldn’t blow up - right now it gives argument errors. It ought
to behave identically to
render :update => true, :status => 404 (Rails 2.2.2 converts the first
form to the second).

(3) with_tag is completely broken, as it tries to use the outer class as the
subject of ‘with_tag’, rather than the have_tag matcher that it lives
inside.

Was it working before and the upgrade broke existing specs? Or is this
a general observation?

Yes, the upgrade broke existing specs… it used to work fine as of
rspec 1.1.4.
The breakage appears to have something to do with the ‘subject’
functionality.

(4) assigns(:xxx) will give really bad errors if your class doesn’t happen
to define == in such a way that it can equate to FalseClass.

Can you provide an example?

Let’s say I have a simple object class Foo, defined as:

class Foo
def initialize(bar)
@bar = bar
end
attr_reader :bar

def ==(other)
self.bar == other.bar
end
end

and a controller that sets a model variable @foo to Foo.new.

If you run an rspec controller spec and ask it about assigns(:foo), it
will complain with
an error about how it doesn’t know what the ‘bar’ method is on
FalseClass. It does this
the moment you ask for assigns(:foo).

Not the biggest deal once you understand what’s going on (you can
solve it by making the == method smart
enough to return false unless other is a Foo class) but a very
confusing error to track down.

=N


#7

On Wed, Feb 11, 2009 at 2:52 PM, removed_email_address@domain.invalid
removed_email_address@domain.invalid wrote:

rspec 1.1.4.
The breakage appears to have something to do with the ‘subject’
functionality.

Nathan,

Taking a closer look at this - before we introduced the implicit
subject, nested with_tag and without_tags were passing in the
ExampleGroup. The matcher was (and still is) ignoring that argument,
and using the HTML it got from the have_tag call.

There are also a number of specs in rspec’s own suite that show that
this works correctly. These pass against rails 2.0.5, 2.1.2, 2.2.2,
2.3.0 and edge (as of earlier today).

Take a look at
http://github.com/dchelimsky/rspec-rails/blob/333810bf6f062599bd39007a3fe32ba227a4b32a/spec/spec/rails/matchers/assert_select_spec.rb
and scroll down to 289, for example.

Can you show me an example of what’s failing for you? Spec and subject
code, and the failure message?

Thanks,
David


#8

On Wed, Feb 11, 2009 at 2:52 PM, removed_email_address@domain.invalid
removed_email_address@domain.invalid wrote:

some way? Or just to not blow up?

It shouldn’t blow up - right now it gives argument errors. It ought
to behave identically to
render :update => true, :status => 404 (Rails 2.2.2 converts the first
form to the second).

Fixed. 2 down, 2 to go.


#9

On Wed, Feb 11, 2009 at 2:52 PM, removed_email_address@domain.invalid
removed_email_address@domain.invalid wrote:

def initialize(bar)

If you run an rspec controller spec and ask it about assigns(:foo), it
will complain with
an error about how it doesn’t know what the ‘bar’ method is on
FalseClass. It does this
the moment you ask for assigns(:foo).

Not the biggest deal once you understand what’s going on (you can
solve it by making the == method smart
enough to return false unless other is a Foo class) but a very
confusing error to track down.

Well - you shouldn’t have to do such a workaround. Fixed: 3 down, 1 left


#10

Thanks for making the other fixes! I don’t have a ‘have_tag’ example
handy (replaced all the instances with more compact with_tag syntax)…
I’ll try to get to it later today and send it to you personally.
=N