Issues with the trunk of rspec-rails

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

(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

On Tue, Feb 10, 2009 at 2:02 PM, Nathan W. [email protected]
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

On Tue, Feb 10, 2009 at 3:02 PM, Nathan W. [email protected]
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: [email protected]
web: http://joshknowles.com

On Tue, Feb 10, 2009 at 10:49 PM, David C. [email protected]
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

Snipping down to relevant questions:

On Feb 10, 8:49 pm, David C. [email protected] wrote:

On Tue, Feb 10, 2009 at 2:02 PM, Nathan W. [email protected] 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

On Wed, Feb 11, 2009 at 2:52 PM, [email protected]
[email protected] 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

On Wed, Feb 11, 2009 at 2:52 PM, [email protected]
[email protected] 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.

On Wed, Feb 11, 2009 at 2:52 PM, [email protected]
[email protected] 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

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