Rspec: Capybara server map a directory - ruby-on-rails

I have a set of files in a folder under spec/support/fixtures directory. I need those files to be accessible through an uri such as "http://127.0.0.0:#{Capybara.current_session.server.port}/test_fixtures"
After many trail and errors I ended up the following solution: In rails_helper.rb I added the following code:
Capybara.app = Rack::Builder.new do
map '/' do
run Rails.application
end
map '/test_fixtures' do
run Rack::File.new('spec/support/fixtures')
end
end.to_app
It works well, but the solution to re-create Capybara app does not seem elegant to me. I'm looking for a better solution... or is it ok like this ?
Thanks

For your stated goal you have implemented things correctly and that is exactly what the Capybara.app setting is meant for. The only thing I would recommend doing is moving it into a separate file and requiring that file in your rails_helper.

Related

what to set in Capybara.app for a Middleman project?

In the env.rb to use Capybara you should setup Capybara.app = something
Middleman is based on sinatra so I was thinking to use Sinatra::Application but gives an error
Anyone know what should be put to set up Capybara in the proper way?
Although I've recently stated this answer in the (recently closed) GitHub issue that #bhollis gave, I should fill in the answer here as well in keeping with the spirit of StackOverflow.
In a spec_helper.rb file added to a spec folder in the root of your Middleman project, the assignment I've used is Capybara.app = Middleman::Application.server.inst - however, I configure it a little bit too like so:
Capybara.app = Middleman::Application.server.inst do
set :root, File.expand_path(File.join(File.dirname(__FILE__), '..'))
set :environment, :development
set :show_exceptions, false
end
A full example of this using RSpec can be found here.
The answer will eventually be at https://github.com/middleman/middleman/issues/895

Can I run a Rails engine's specs from a real app which mounts it?

I have a Rails Engine meant to provide some models and controllers to a larger project of ours. There's a pretty decent set of specs for the Engine, using a bunch of mocks and some full-scale models and controllers within the engine's dummy app to make sure the Engine is doing what it's supposed to and working with the larger application.
However, even with all tests passing, I frequently find broken behavior when I update the engine in the larger application. If my tests are passing but the behavior is broken, clearly something's wrong with the tests, but what? Am I mocking too much, or not enough?
To get me closer to figuring this out, I'd like to be able to run the engine's tests from inside the full application. This seems like it should be possible, but I don't understand rspec thoroughly enough to get a handle on how.
(This is related to this question but not quite the same; I'm not trying to run all the specs from one command, just to run the engine's specs within the full app environment. This also seems to be related. Actually, I've read every question tagged with both rspec and rails-engines--there aren't many--and they're all either not what I need, or unanswered.)
The simplest solution would be to specify the paths in rspec command. If you have directory structure
/project
/engine
/engine_2
Then you do and should run all the specs
cd project
rspec spec/ ../engine/spec ../engine_2/spec
But if you want to run specs on Continous Integration or just this doesn't seem to be comfortable I solved this problem with a customized rake spec task, changing the pattern method.
lib/task/rspec.rake should look like this
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
task :default => :spec
RSpec::Core::RakeTask.module_eval do
def pattern
extras = []
Rails.application.config.rspec_paths.each do |dir|
if File.directory?( dir )
extras << File.join( dir, 'spec', '**', '*_spec.rb' ).to_s
end
end
[#pattern] | extras
end
end
In engine class you add a path to config.rspec_paths
class Engine < ::Rails::Engine
# Register path to rspec
config.rspec_paths << self.root
end
And don't forget to initialize config.rspec_paths somewhere in a base project.
If you want to add factories then you can create initializer, you can find solution somewhere here on stackoverflow.
Not sure if this solution is the best but works for me and I am happy with that. Good luck!

sandbox testing environments exist for TDD'ing command line application

I'm writing a command line command but want to TDD it. I'll be creating and deleting files and was wondering if there's a sandbox testing gem or something like that. I'm using ruby and rspec.
Depends on what you're trying to do, but I test most of my command line Ruby by mocking out the file system and STDIN/STDOUT. Using dependency injection I often end up with something along these lines:
describe Add do
it 'writes the result to standard out' do
console = mock('STDOUT')
console.should_receive(:puts).with('5')
Add.new(console).execute(3,2)
end
end
class Add
def initialize(out = STDOUT)
#out = out
end
def execute(command_line_args)
#out.puts(command_line_args.inject(:+))
end
end
Add.new.execute(ARGS)
By using default values I can inject in the test, but leave it out of the production code.
Hope that helps!
Brandon
The template generated by the newgem install_cucumber generator uses a pattern that I like quite a bit. Have a look at the support/env.rb and support/common.rb files it creates:
https://github.com/drnic/newgem/blob/master/rubygems_generators/install_cucumber/templates/features/support/env.rb.erb
https://github.com/drnic/newgem/blob/master/rubygems_generators/install_cucumber/templates/features/support/common.rb
Use of it in test looks like this:
in_tmp_folder do
# The current directory is now a generated tmp folder.
# If you stick to relative paths, everything you do in here should be safe
end
The files linked to above are for using this in cucumber tests, but it could easily be adapter to whatever framework you're using. The env.rb above deletes the tmp folder before each test starts.
You might also want to take a look at the sandbox gem.
gem install sandbox
Example usage is here: https://github.com/bdimcheff/sandbox

How can I get Rspec2 to support models and specs in a different path?

I have two rails projects which share the same models (a public website and a an admin site) via a git submodule.
In my application.rb file I have added the following line: config.autoload_paths += ["shared/models", "shared/lib"], and this works fine while running the Rails applications, however when I try to run specs it seems to load the routes.rb file first, and then the application.rb file - which means that the specs error out - especially with devise.
In addition to this, Rspec wont pickup the specs in the shared/spec path - is there any way to add this path to the spec task, like do I need to setup my own rspec.rake file duplicating the task or something like that?
Cheers
To load shared/models, you do have to add it to config.autoload_paths.
Then to load your spec from shared/spec, add this to spec_helper.rb:
shared_model_specs = config.filename_pattern.split(",").collect do |pattern|
Dir["shared/spec/models/#{pattern.strip}"]
end.flatten
config.files_to_run.concat shared_model_specs
Just a side note for other guys interested, if your spec files are in the normal spec folder but under a customized sub folder, you can load it like this:
config.include RSpec::Rails::ModelExampleGroup, :type => :model, :example_group => {
:file_path => config.escaped_path(%w[spec shared models])
}
PS: I would recommend putting the shared code or modules into a gem, then use them in the two projects. This way the gem contains its own tests and referencing it from multiple projects is much easier and organized.

Exclude Sub Directory on Class Eager Load

I am facing an issue where my Rails application is set to cache classes when run in the staging or production environment. While load_paths only contains 'app/models', it appears that the initialization steps recursively caches everything in 'app/models'.
# Eager load application classes
def load_application_classes
if configuration.cache_classes
configuration.eager_load_paths.each do |load_path|
matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
require_dependency file.sub(matcher, '\1')
end
end
end
end
The problem in this is that we have a sub directory within 'app/models' that contains files with require statements that reference a concurrent JRuby environment. Since Rails knows nothing of this environment our application breaks on load.
As it stands, here are the proposed solutions...unfortunately only #1 is ideal.
1) The simplest solution would be to exclude the culprit sub directory, but have not found anything how to accomplish this.
2) Monkey patch the load_application_classes method to skip the specific sub directory.
3) Move the sub directory out from under 'app/models'. Feels a bit hackish and would require quite a few code changes.
Thoughts?
As a temporary measure you could go with a version of option 2 and override the definition of load_application_classes, replacing it with an empty implementation. That would force you to explicitly require the classes you need but it would give you complete control over what gets loaded and would be a completely transparent solution.
It sounds like your application is sufficiently sophisticated that it's growing beyond the Rails framework. I know that this doesn't directly answer your question so appologies in advance but you may want to consider looking at an alternative Ruby framework like Merb. Rails is great but sooner or later you bump into edge of the framework - sounds like that's where you are now.
We made the switch to Merb last year and haven't regreated it.
Chris

Resources