I have a helper class, ApplicationHelper, that has a method, build_links(). I have another class, AppleClass, that refers to that method.
AppleClass
def foo
....
build_links
end
end
ApplicationHelperClass
def build_links
main_app.blah_path(1)
end
end
The complication here is that there's an Engine, so I usually explicitly reference "main_app.blah_path" not just "blah_path".
The test against foo passes by itself, in its file, and when I run all helpers. It fails, though, when I include it in all the unit tests - "rake spec:suite:unit", and with our entire suite. All Apple tests pass, all ApplicationHelper tests pass. The only failing ones are when one method is referring to the other method, in routes, outside of the engine, in the full suite.
`undefined local variable or method `main_app' for #
<RSpec::Core::ExampleGroup::Nested_45::Nested_1:0x007fc134b30130>`
My suspicion is that the test helper, or some config, is not loading the engine's routes early enough, and thus links to "main_app" don't make sense. If I remove main_app, the test fails until it's run in the main suite.
Does anyone have tips on troubleshooting what's really going on? Also, could I kickstart the routing somehow in test_helper?
ruby-1.9.3-p385, rails 3.2.13, rspec 2.13.0
I had the same issue and found that if I added this method to the top of my Controller RSpec test case, then it resolved the issue entirely.
def main_app
Rails.application.class.routes.url_helpers
end
I think this issue is related to this question
Related
I have a Rails model with an after_create callback, that has code which interacts with an external API. That code is getting executed and content on another app is being created when I run rspec tests.
I want to do something such as:
after_create :external_api_code, unless: testing?
def testing?
#what goes here to recognize that the object is being created in a test?
end
To check whether or not code is running in the test environment:
Rails.env.test?
To avoid running external API code in RSpec, put this in your configuration block:
RSpec.configure do |config|
config.before(:each) do
allow_any_instance_of(Model).to receive(:external_api_code).and_return(return_value)
end
end
To actually run the code in the test that needs it run:
allow_any_instance_of(Model).to receive(:external_api_code).and_call_original
One of possible solution may be to just stub the external_api_code in all tests and unstub it where its call is really needed. Of course this solution will work but it requires some monkey business because you have to place the stubbing code in all test files of your project. This is possible RSpec code to do it:
before(:all) do
User.any_instance.stub(:external_api_code)
end
like this in your model test case file.
When I run view specs manually (zeus rspec or rake spec) I am getting errors raised if Devise or CanCanCan helpers are present in the view
Failure/Error: <% if user_signed_in? %>
ActionView::Template::Error: undefined method `authenticate' for
nil:NilClass
Failure/Error: <% if can? :update, #object %>
ActionView::Template::Error: undefined method `authenticate' for
nil:NilClass
When the same specs are run via Guard, no errors are raised and the specs pass.
Adding the following to the view spec causes both Guard and manually launched specs to pass.
...
#ability = Object.new
#ability.extend(CanCan::Ability)
controller.stub(:current_ability) { #ability }
controller.stub(:user_signed_in?) {false}
...
(I also tried including config.include Devise::TestHelpers, type: :view in a support file but this did not appear to do anything)
Why would Guard-launched and manually-launched specs behave
differently?
Are these controller stubs the 'correct' way to deal
with this issue?
Why would Guard-launched and manually-launched specs behave differently?
The best way is to run Guard in debug mode: bundle exec guard -d. It will show you the actual rspec command being run. Then, you can compare that to how you're invoking rspec.
The second thing could be: you may be running different versions of gems. Try bundle exec rspec vs bundle exec guard. There shouldn't be differences. You can then experiment with zeus, etc.
Are these controller stubs the 'correct' way to deal with this issue?
I'd say it's best to use Cucumber/Capybara for testing views. It isn't as fast and the effort to mock the views is probably just not worth the time.
But otherwise, it doesn't matter how you stub/mock as long as you're testing what matters. For views, I think that means testing to make sure the right instance variables are used to generate the views. Testing the actually html generated probably isn't too convenient.
Views change often, too - so too much testing there can be a waste of time with little gain. Even if you make errors in views, they're usually easy to spot, quick to fix and there aren't too many edge cases. (Those are usually handled by controllers). So again, using Cucumber+Capybara gives you more tools, more flexibility and enough coverage without sacrificing your freedom to change things without being forced to update tests as well.
The reason for devise helpers is to get sign_in and sign_out working. That's pretty much it. So if those don't work, you likely don't have the helper included.
I also tried including config.include Devise::TestHelpers, type: :view in a support file but this did not appear to do anything
Are you sure that support file was actually included? Usually nowadays you have to do that explicitly in the spec_helper.rb file.
I'm currently working on a project and we started migrating our tests to isolated test (no rails dependency, and using stubs and mocks).
The thing is that until all the current tests are being isolated, we have to run the tests together with the isolated tests, which will start the rails environment.
The problem comes when, in the isolated tests, there is a fake class (class Foo; end;), it will override the original class for the rest of the tests.
Example:
In the foo_spec.rb we have this line
class Bar; end;
This would override the Bar class for the next nonisolated tests, and would cause a lot of fails.
There are 2 approaches I could figure in order to get rid of this:
- either comment out the fake classes when the tests are run with rails env
- put the isolated tests in another folder and run them separated from the rest (this would make more sense)
Can you think of a nicer way to deal with this?
we are using rspec (which should not change anything) and have our rails spec located in spec with their own spec_helper.rb file that is loading the env and all the ugly stuff.
in spec_fast folder we have all the spec that can run without rails, with their own spec-helper that only loads our independent lib folder.
for our ci-server we let both spec folder run in a different task:
if Rails.env.test?
require 'rspec/core/rake_task'
require 'ci/reporter/rake/rspec'
RSpec::Core::RakeTask.new(:all_fast) do |t|
t.pattern = 'spec_fast/**/*_spec.rb'
end
RSpec::Core::RakeTask.new(:all_slow) do |t|
t.pattern = 'spec/**/*_spec.rb'
end
task :all => ["ci:setup:rspec", :all_fast, :all_slow]
end
it should also be possible to just put them into separate subfolders like spec/rails and spec/fast but i did not try it out because it means to do a lot of path-changing in spec-files.
I don't know if it's right, but I end up not actually assigning such contextual dummy manually created dummy classes to constants.
Instead of:
#no
class Foo
#something
end
Instead:
foo = Class.new do
#stuff
end
And you can foo.new or foo.class_method to your heart's content. Could be in #foo too. But you aren't assigning it to the constant Foo like ordinary class definition does, you're creating an 'anonymous' class and assigning it to an ordinary variable, scoped to just within the area you need it.
Note: I'm not saying this is "right" way to do things with rspec, I never feel like I know the right thing to do, the right thing to do might be to somehow not create classes like this at all, or use some weird factorygirl thing which I don't understand or something. But when I need to create 'dummy' type classes just to the scope of a particular test or block, that's what I do.
In my RSpec controller test, I'm trying to test a particular action that makes a call to a subfunction. But I don't want the test to include the call to that subfunction. (it'll raise an error that simply cannot be fixed in my dev environment)
What's the best way to omit this subfunction call from this controller action while I'm running a test over it?
Thanks.
You can stub that subfunction call in the before block of your rspec test for that function like so
describe "test for the main_action"
before(:each) do
controller.stub!(:sub_action).returns(true)
end
end
Then none of your test examples would actually call this sub_action.
Just for semantics, Rspec always runs in test environment not in development but I gather what you mean.
How would I quickly debug helper methods in script\console. I'm talking about making changes and then debugging, over and over again.
This is a lot easier with Model methods, since all I have to do is use
reload!
to test the updated code, whereas to test a helper method, I have to do something like this
foo = ActionView::Base.new
foo.extend YourHelperModule
each time to I want to test a change.
What does reload! do? and can I modify it to add the above lines of code?
I don't think you can do that without hacking Rails. However, there's a workaround - debugging helper method in rails debugger:
1) gem install ruby-debug
2) ruby script/server --debugger
3) place <% debugger %> into some view and open that page in browser
4) server window "turns into" console, where you can debug helper methods
5) 'return' command ends the debugging
If you modify the helper method and run the debugger again, you will get recent version of the method.
More info about debugger is here: http://railscasts.com/episodes/54-debugging-with-ruby-debug
I would suggest not using script console and writing tests in either Test::Unit or rspec instead. Google should get you pointed in the right direction there is a ton of information out there.
If you're doing something "again and again" then you should be automating it. Assuming you know what your helper function should do then as mentioned elsewhere you should be able to write a test (or tests) for it.
Here's a sample that tests application_helper. It lives in my test/unit directory:
require 'test_helper'
class ApplicationHelperTest < ActiveSupport::TestCase
include ApplicationHelper
test "number_as_pct shows 2dp as default" do
assert_equal "1.10%", number_as_pct(0.011)
end
test "number_as_pct shows more dp when required" do
assert_equal "1.1000%", number_as_pct(0.011, :precision => 4)
end
end