Rails 3.1 RC5 Mountable Engine testing with Spork - rspec2

I've been able to get RSpec, Cucumber, and Autotest to work against my Rails 3.1 Mountable Engine. Where things fall down is trying to integrate Spork into the mix. Spork runs fine, and my tests use Spork, but the problem I'm having is that Spork doesn't reload models unless I bring down the Spork server which isn't exactly efficient. I'm using factory_girl as well. I tried various things using Spork.trap_method, yet nothing has worked.
Here's the gems I'm using (although I have since abandoned Spork in my project due the grief it was causing me):
rails (3.1.0.rc5)
spork (0.9.0.rc9)
rspec (2.6.0)
rspec-core (2.6.4)
rspec-expectations (2.6.0)
rspec-mocks (2.6.0)
rspec-rails (2.6.1)
factory_girl (2.0.3)
factory_girl_rails (1.1.0)
cucumber (1.0.2)
cucumber-rails (1.0.2)
Thanks,
-Damien

I figured out my problem. It was actually Autotest and not Spork. I've moved from a mountable engine to a standard engine (plugin) since it ended up being a better fit for what I needed.
I'm now using the released version of Rails 3.1.
In this scenario, I figured things would be easier, but I encountered the same issue. Anyway, this ended up being the fix for testing a non-namespaced engine (mountable), although with a few path tweaks, I believe it will work.
Add an .autotest file to the root of the project with the following:
Autotest.add_hook :initialize do |at|
at.add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
"spec/models/#{m[1]}_spec.rb"
end
at.add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
["spec/controllers/#{m[1]}_spec.rb",
"spec/functional/#{m[1]}_spec.rb"]
end
at.add_mapping %r%^app/helpers/(.*)_helper.rb% do |_, m|
["spec/views/#{m[1]}_view_spec.rb",
"spec/functional/#{m[1]}_controller_spec.rb"]
end
at.add_mapping %r%^app/views/(.*)/% do |_, m|
["spec/views/#{m[1]}_view_spec.rb",
"spec/functional/#{m[1]}_controller_spec.rb"]
end
end
I came up with the solution when I ran across this answer on another question: how to tell autotest to correctly track changes in app source?, as well as other examples found around the web.
Hope this helps someone else out.
[Edit 2011-09-20]
Fixed the Cucumber/Spork problem with a "hack." Within the Spork.each_run block, I forced a reload of the models and controllers like so:
ENGINE_ROOT=File.join(File.dirname(__FILE__), '../../')
# Couldn't get spork to reload models, hence the reason for this hack
Dir[File.join(ENGINE_ROOT, "app/models/*.rb")].each {|f| load f }
# or controllers...
Dir[File.join(ENGINE_ROOT, "app/controllers/*.rb")].each {|f| load f }
It seems like there should be a better way...

Related

Reasons rails is not stopping at debugger

In our application in Ruby on Rails (4.0.2) we've always had this problem. I never understood quite well why the application doesn't stop at the debugger statement sometimes.
In some cases, we discovered some constant behavior such as: in a test, it never stops if the statement's placed at the end of the test block like this:
describe '#some_method' do
it 'should do something as in the requirements etc' do
model_x = FactoryGirl.create(:model_x)
model_x.should be_valid
# ...more code
model_x.should be_valid
debugger
end
end
To make debugger stop at the statement, we have to add a p "foo"
after it.
In some other misterious cases it doesn't stop, but if you add prints before and after, it does.
When debugging a delayed job, you may have to require the debugger and add some prints for it to stop.
I can't find a deterministic reason why the debugger skips the debugger statement sometimes.
Can someone list the reasons for this behavior?
Obs: I'm using byebug right now, but I know that the plain debugger has this behavior too.
Obs2: From my Gemfile.lock:
byebug (2.4.0)
columnize (~> 0.3.6)
debugger-linecache (~> 1.2.0)
...
debugger (1.6.3)
columnize (>= 0.3.1)
debugger-linecache (~> 1.2.0)
debugger-ruby_core_source (~> 1.2.4)
debugger-linecache (1.2.0)
debugger-ruby_core_source (1.2.4)
This is a known issue in the debugger gem, see here (bullet point number three).
It seems that you are interested in why it doesn't work. The following is the explanation:
What debugger does is watching some events provided by ruby that tell the debugger when to stop. In this case, the debugger tracks what we call a line event that is triggered once per line executed, so in the case of the last line of a method, the debugger will stop in the next line event, which actually happens outside the method that is being debugged.
In byebug, however, I also track what we call return events, that are called every time a method finishes. That's why I'm able to stop execution before the method actually finishes.
Hope this helps.

Rails 2.3 and minitest

I would like to try minitest with an existing Rails 2.3.14 application. I already tried several approaches but none of them seem to work.
It essentially boils down to this. When I add minitest to the Gemfile, all tests I run with bundle exec rake test are NOT executed with minitest.
The problem is that most of the test cases extend the ActiveSupport::Testcase or ActionController::Testcase (which extends ActiveSupport::TestCase).
By looking at the code of this class I saw that it already (somehow) suppports MiniTest:
class TestCase < ::Test::Unit::TestCase
if defined? MiniTest
Assertion = MiniTest::Assertion
alias_method :method_name, :name if method_defined? :name
alias_method :method_name, :__name__ if method_defined? :__name__
else
...
end
(see https://github.com/rails/rails/blob/2-3-stable/activesupport/lib/active_support/test_case.rb for complete code)
My question here is:
Is it somehow possible to use minitest instead of test::unit in Rails 2.3 without having to extend (MiniTest::Unit::TestCase)
Any testing framework is made of two things, a way to define and run tests (call this the test runner) and an assertion framework.
Looking at ActiveSupport it seems that if MiniTest is defined at all, running the rails Unit test runner will default to using MiniTest's assertions classes. This means you get to use Minitest's assertion syntax.
Getting MiniTest defined should just be a case of requiring 'minitest\unit'.
However if you want to use the runners, then you need to derive from the MniTest framework test fixture base classes.
There is a step by step walkthrough in railscasts for setting it up yourself.
It boils down to:
Remove test_unit from your config/applications.rb
Add the minitest gem to your gem file "Gemfile"
Setup the environment in a helper file you can include into your tests
Add a rake task to run the tests. (/lib/tasks/minitest.rake)
Railscasts has the details.
If you don't want to change your existing tests to do that.. then you have to monkey patch Test::Unit to redefine TestCase to either be the chosen MiniTest base class or something that derives from one. This is the approach that this gem takes and may give you some ideas on how best to go about that.
The other solution is to do a search/replace through your code to switch the base classes of the test cases.
I hope this helps.
I Updated my answer and remove the following as out of date:
minitest-rails has rightly been pointed out as it works for Rails 3.1 only.
This gem seems to be old (26th March 2009) but it may help. Check the source code if you need hints to do something similar.

How to resolve name collision between i18n's Hash#slice and ActiveSupport's Hash#slice

I'm working on a Rails 2.3.14 project, which uses 0.6.0 of the i18n gem and 2.3.14 of the ActiveSupport gem. Both of these define a Hash#slice method (i18n's; ActiveSupport's), but they function differently: the i18n version uses Hash#fetch, and so raises an i18n/core_ext/hash.rb:4:in 'fetch': key not found (IndexError) exception if any requested key is missing, while the ActiveSupport version happily ignores missing keys, and the rest of ActiveSupport depends on that happy ignoring.
In my app, the i18n version is loading first (because, incidentally, faker is loading it as a dependency), so when ActiveSupport tries to depend on the ignore-missing-keys behavior I get the exception.
Is there a way to tell Rails to load ActiveSupport before faker and i18n?
You could also monkey patch the Hash class after the gems are required. You could just paste the contents of ActiveSupport's hash/slice.rb into your app somewhere. The URL can be found here:
https://github.com/lifo/docrails/blob/master/activesupport/lib/active_support/core_ext/hash/slice.rb
That would override the definitions from the gems though, so YMMV.
I used #Eugene's idea of reverting back to ActiveSupport's method (and so he gets the happy green checkmark), but did it in such as way as to avoid duplicating the code. First we test to see if we're using the i18n version, and if we are we use remove_method to wipe it out (it was added by opening the class) and let the ActiveSupport 2.3.14 module fill in (note I didn't use undef, which also wipes out the module's override).
So into an initializer goes the code:
begin
{}.slice(:a) # ActiveSupport's slice is fine with this; i18n's is not
rescue IndexError
class Hash
remove_method :slice #kill i18n's implementation, allow the ActiveSupport module to work
end
end
If you can't control the order of loading, you could try the method in this blog post http://banisterfiend.wordpress.com/2010/11/04/baking-module-methods-into-classes-with-alias_method/
I've used it and it worked for me, but that was with modules I'd written myself.
I've opened an issue on the i18n project to make slice more safe, and created a PR to implement it. You can find the issue / PR at https://github.com/svenfuchs/i18n/pull/292.
To manually patch yourself, you can just add if has_key?(key) after the fetch.

How to get awesome_print to work in pry/ruby-debug in running app

I super love awesome_print and ruby-debug but I can't get them to work together. AwesomePrint returns HTML for formatting but I'd it seems like ruby-debug and pry don't like multi-line output so I always end up with a complete mess. This is what it looks like when I run ap from pry or ruby-debug (in a running app).
pry(#<#<Class:0x000001117f2f58>:0x000001117ef560>)> ap #user
=> "#<User:0x000001111de888> {\n<pre>:id</pre><pre> => </pre>\n ... snip ...}"
Has anyone had any luck getting awesome_print to work in ruby-debug or pry on a running rails app? Am I just doing something wrong? I would also be happy with multi-line pp, at least that would be a huge upgrade.
Thanks!
Specify awesome_print in your Gemfile. Bundler runs things in its own context (not exactly know how or why this is done)

Setup Factory Girl with Test::Unit and Shoulda

I'm trying to set up Factory Girl with Test::Unit and Shoulda in Ruby on Rails. I have installed the gem, created my factory file under the test/factories directory, and created my spec file under the test/models directory. The current error I'm getting is 'ArgumentError: No such factory: test', which leads me to believe that the test_factory.rb file is not being loaded? Any idea as to what I should change?
Here are my files.
#test/factories/test_factory.rb
Factory.define :test do |t|
t.name 'test_spotlight'
t.label 'test spotlight label'
end
and
#test/modes/test_spec.rb
require 'test_helper'
require 'factory_girl'
class TestTest < Test::Unit::TestCase
def setup
#test = Factory.build(:test)
end
context "A test" do
should "save with the minimum requirements" do
assert #test.save
end
end
end
I've run into this problem on one of my projects too. I'm not sure precisely what's causing the initialization code to be skipped but you can force load the factory definitions like this:
require 'factory_girl'
Factory.find_definitions
Hope this helps.
Try putting this in test_helper.rb:
require 'factory_girl'
Dir.glob(File.dirname(__FILE__) + "/factories/*").each do |factory|
require factory
end
Just discovered factory_girl_rails, where it says the autoloading is the only extra thing it has https://github.com/thoughtbot/factory_girl_rails
I had the same problem. Eventually I made do by putting all my factories in "/test/factories.rb" and writing the following lines in my "/test/test_helper.rb" file:
require 'factory_girl'
require File.dirname(__FILE__) + "/factories"
you could do the same thing for multiple files by requiring them in the test_helper. I haven't yet figured out why the auto-include that's mentioned in "factory_girl's" readme doesn't happen.
I also managed to get rid of this issue by putting this line into my environment.rb:
config.gem "factory_girl", :source => "http://gemcutter.org"
Make also sure you have the latest gem:
Name changed from "thoughtbot-factory_girl" to "factory_girl", source changed from "http://gems.github.com" to "http://gemcutter.org".
In case you had this issue with ruby 1.9.2, require expects the expanded path.
File.expand_path("test/factories.rb")
This patch solved my problem. I just sent a pull request.
After that you can add this to your test_helper.rb:
require 'factory_girl'
FactoryGirl.find_definitions
If I only required 'factory_girl' in test_helper.rb, I would get the same behavior you mentioned, yet if I required it in my config/test/environment.rb (note I use environmentalist) it would properly find the Factory definition without any issue.
I tried this after reading the factory girl rdoc where it says to put config.gem in your environment.
I also ran into the problem - after updating FactoryGirl to 1.3.2 - that factories from test/factories were not loaded automatically any more.
I could get rid of the problem by adding the code from dg into test_helper.rb:
Dir.glob(File.dirname(__FILE__) + "/factories/*.rb").each do |factory|
require factory
end
When running single tests in Textmate, everything worked fine, but running e.g. all unit tests from the command line using rake test:units failed with a DuplicateDefinitionError (I read that it has probably something to do with ruby 1.8.x). So I slightly changed the code:
if (!Factory.factories || Factory.factories.empty?)
Dir.glob(File.dirname(__FILE__) + "/factories/*.rb").each do |factory|
require factory
end
end
Have you tried moving the
require 'factory_girl'
to your test/test_helper.rb ?
The factory auto-loading mechanism may depend on where the the require is called. It could be trying to find factories *test/models/factories/** instead of *test/factories/**
Instead of naming your factory file test_factory.rb, try naming it factory.rb
Interesting. I had a similar problem trying to get cucumber to work with factory_girl. I had originally configured factory_girl to be looked for ('config.gem') but not loaded in the cucumber environment and fully required in 'features/support/env.rb', same as cucumber does for webrat, etc. That only started to work when I explicitly told factory_girl to find its definitions as Kenny suggested above.
When I removed the require statement from env.rb and fully required factory_girl in the cucumber environment, the effect went away and factory_girl worked out of the box.
So it really seems to be a question of when (or in which context) factory_girl gets loaded.
Since different people are using different versions of Rails (2.x and 3.x being the most common now), it is important to include the other pertinent pieces of your environment (the most important being which version of Rails you're on). From the factory_girl web page, version 1.3.0 documentation (http://rubydoc.info/gems/factory_girl/1.3.0/frames):
If you want to use factory_girl with Rails 3, use the
factory_girl_rails gem, not this one.
If you want to use factory_girl with Rails versions prior to Rails 3,
use version 1.2.4.
If you're having trouble with the loading, I'd suggest making sure that you are using the right version. The versions of factory_girl greater than 1.2.4, I'd assume, are brought in as dependencies for the 'factory_girl_rails' (Rails 3.0+) gem.
I added
require 'factory_girl'
require File.dirname(FILE) + "/factories"
to spec_helper.rb whiche helped, but then I rememberd Spork can sometimes ba a bit of a problem, so I restarted Spork without the require and then it worked fine.

Resources