Skip to content

ree187, rspec 1.3.2, rails 2.3.14, cpybara, steak 1.1.0, rack-test don't like Rails URL helpers #557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
MattRogish opened this issue Jun 4, 2012 · 6 comments

Comments

@MattRogish
Copy link

Hi everyone,

It was suggested I post an issue here - I'm not sure what is going on, but I have built a test app to show you what I mean:

https://github.com/MattRogish/BrokenURLHelpers

Out of the box (create a gemset etc.) running bundle exec rake spec:acceptance will fail.

ArgumentError in 'Fix rspec and rack/test
In order to keep my code DRY
As a test driven developer
I want Rails2 route helpers to work
Broken helper #1'
wrong number of arguments (0 for 1)
(eval): 4:in `products_path'
./spec/acceptance/products_spec.rb:23:

ArgumentError in 'Fix rspec and rack/test
In order to keep my code DRY
As a test driven developer
I want Rails2 route helpers to work
Broken helper #2'
wrong number of arguments (0 for 1)
(eval): 4:in `new_product_path'
./spec/acceptance/products_spec.rb:27:

This is due to the addition of Rack::Test::Methods (https://github.com/MattRogish/BrokenURLHelpers/blob/master/spec/acceptance/products_spec.rb#L10)

If I remove this line, everything works. Of course, I can't use put and other methods to test my API, which is the whole reason for using Rack::Test to begin with. I'd like to use the ActionController helpers to keep things DRY (so I don't hard-code paths) but these two are at odds.

I've stepped through the call stack with the debugger and it seems like rspec's method missing super call is sending the method over to Rack::Test instead of ActionController and then it gets bogged down there. In the non-broken call, though, it doesn't even get to rspec's method_missing...

Working helper stack:
https://gist.github.com/2870966

Broken helper stack:
https://gist.github.com/2870971

I'm not sure what the root cause is - I'm sure running old versions of all of these things doesn't help -- but as I'm on a legacy product that doesn't have an easy upgrade path to Rails3 (I'm not sure if it's even fixed in Rails3), I'm fine with forking and fixing locally.

Does anyone have any pointers or commits where it may be fixed to help point me in the right direction?

Thanks!!!

Matt

@alindeman
Copy link
Contributor

Larger question: are you sure you mean to be mixing steak (which is supposed to sit on top of capybara, which itself is an abstraction from something like rack-test) and direct use of rack-test?

@alindeman
Copy link
Contributor

In fact, capybara has the feature and scenario DSL baked right in these days. I don't really know what steak offers anymore.

Edit: It's only RSpec 2 compatible. Whoops :(

@alindeman
Copy link
Contributor

Wow, this is a crazy issue.

Including Rack::Test::Methods adds a request method that is a generic form of get, post, etc..: https://github.com/brynary/rack-test/blob/v0.6.1/lib/rack/test.rb#L105-115

Meanwhile, ActionController::UrlWriter uses an optimization technique that, if request is defined, takes a different path to generating the URL helpers: https://github.com/rails/rails/blob/v2.3.14/actionpack/lib/action_controller/routing/optimisations.rb#L23-28

So the URL route generation code is calling request to try to get some attributes off of it, thinking it's an object that represents a web request. In these tests, however, it's a method that will make a fake request.

(Side note: the exception is caused by calling request with no arguments)

One solution is to undef_method :request after the include Rack::Test::Methods:

  include ActionController::UrlWriter
  include Rack::Test::Methods
  undef_method :request

I'm not too familiar with RSpec 1, unfortunately, but it seems like most of these issues would go away if your spec were a wrapper around a Rails integration test (like request specs are in RSpec 2). Request specs have access to everything you need, I think, and while they don't use rack-test necessarily, they have methods like get, post, etc.. that do similar things but more coupled to Rails.

I don't have the best answer for you; maybe someone else can come along and sweep together my analysis into a less smelly recommendation. I hope I've helped either way. Closing this issue against RSpec for now.

@alindeman
Copy link
Contributor

On the otherrrrrr hand, if you really want to use Capybara, a higher level abstraction for driving a web application, you should use methods like visit instead of get, post, etc..

visit may eventually call rack-test methods, but you won't know about them (because it's an abstraction). Capybara is a great high-level DSL for testing web applications as a user might click around, fill in forms, etc.. though it may be less appropriate if you're testing some API where you can't drive the app as a web browser might.

@MattRogish
Copy link
Author

Wow!! That's amazing! Thank you so much! FYI if you ever have a moment and wouldn't mind letting me know how you debugged it, that would help. I think I may have been on the right track with stepping through the stack, but I missed something along the way.

Thanks again!

@alindeman
Copy link
Contributor

Sure, I'll try to write up something soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants