How to load a spec_helper.rb automatically in RSpec 2 - ruby

When developing gems in Ruby, I almost always need a file in which I can configure RSpec to my needs and maybe before doing that, require some helper modules which should be available in all my spec examples.
In Rails applications a file named spec/spec_helper.rb is used for that. One thing that annoys me is that in the typical Rails environment, you have to require this spec_helper.rb file in every file that contains examples for it to be loaded. In the past I had a lot of problems with this related to changing load paths and relative require paths inside the example files.
Now for my gems, I would wish to have a way to just say RSpec to require the spec_helper.rb file before loading any of the examples files. Independent of the fact if I call rspec executable, or the rake spec task which I may define in my Rakefile.
I know I can tell RSpec only the location of my spec_helper.rb is this spec_helper.rb requires all the example files manually, but I would also like to avoid the additional maintenance of that approach.
Is there a nicer way to accomplish this?

In RSpec 2, the /spec folder is always automatically on your load path. This means that all you need is:
require 'spec_helper'
at the top of your spec files. This will always load /spec/spec_helper.rb, and is the minimum you'll be able to get away with.
This means you don't need a horrid approach such as:
require File.join(File.dirname(File.dirname(__FILE__)), 'spec_helper.rb')
(which needs to be updated for different nesting levels).
Also you can add to your .rspec file the option: --require spec_helper, which will require this file in each spec file, without the manual require statement at the top.

The --require spec_helper line is automatically added to the .rspec file for RSpec 3.0 when you do rspec --init.

Related

How to use multiple spec_helper.rb files

I would like to create and use more than one "spec_helper.rb" to set up different block of codes for each project.
Is that possible? If so, how can I call a specific "spec_helper.rb" in my test file?
spec_helper.rb is not special, it's just a ruby file that you then require from other files (generally the files that define your specs). You can change the name (or have multiple differently named files) that you then require when needed.
Beyond that your question asking about setting up different blocks of code for different projects doesn't make a lot of sense since different projects would each have their own spec_helper.rb by default.

Organizing Cucumber Steps

I am dealing with huge code base where features are grouped by domain in and are kept in separate packages.
+ServicesDomain
    |---+features
         |+step_definitions
+SalesDomain
    |---+features
         |+step_definitions
But there are always some common steps and I could not find a way to keep the common step definitions in some common steps package.
What I would like to know is that, if there is way to keep all the generic steps in some common package and make my domain package depend on generic steps package to leverage the generic steps.
One way of doing it would be to set up a file called features/support/env.rb and add a 'require' statement to this file to include your common steps each time. For instance, the file could contain:
require File.join(File.dirname(__FILE__), ​'..'​, ​'common'​, ​'common_steps'​)
That way your common_steps.rb would be loaded each time.
env.rb is the first file to be run on each Cucumber run.
Have you also heard of the Pickle gem? That might be worth a look as it does something similar by putting common steps into a file called 'pickle_steps.rb'. This comes with handy step definitions for testing models but there would be nothing stopping you editing that file and adding your own.
Hope that is of some help?
Cucumber has a command line option -r that allows you to include specific files. If you run cucumber --help, you can get more information about all the command line options. In ruby you can combine this with a config.yml file to setup globally how cucumber is run in the project. However I suspect you are using java, and I don't know if that applies. You could ask on the cucumber mailing list if thats the case.
An alternative would be to place a file in each support directory e.g. ServicesDomain/features/support and SalesDomian/features/support that just has a require statement that pulls in all the common steps. Cucumber automatically loads all the files in features/support (when it is run from features/..).

rspec require spec_helper in .rspec file

I've noticed that projects such as bundler do a require spec_helper in each spec file
I've also noticed that rspec takes the option --require, which allows you to require a file when rspec is bootstrapped. You can also add this to the .rspec file, so it is added whenever you run rspec with no arguments.
Are there any disadvantages to using the above method which might explain why projects such as bundler choose to require spec_helper in each spec file?
I don't work on Bundler so I can't speak directly about their practices. Not all projects check-in the .rspec file. The reason is this file, generally by current convention, only has personal configuration options for general output / runner preferences. So if you only required spec_helper there, others wouldn't load it, causing tests to fail.
Another reason, is not all tests may need the setup performed by spec_helper. More recently there have been groups of Rubyists who are trying to move away from loading too many dependencies into the test. By making it explicit when spec_helper is required in the test people have an idea what may be going on. Also, running a single test file or directory that doesn't need that setup will be faster.
In reality, if all of your tests are requiring spec_helper and you've make it a clear convention on the project there's no technical reason you can't or shouldn't do it. It just may be an initial surprise for new people who join the project.
With a proper setup, there's no downside at all.
The .rspec file is meant to be project related (and should be commited like any other project source file).
Meanwhile, the .rspec-local is for overriding with personalized settings (and it will let the user override some options only).
(see: https://www.relishapp.com/rspec/rspec-core/v/3-2/docs/configuration/read-command-line-configuration-options-from-files)
Rails projects even use a separate --require rails_helper for Rails-specific RSpec settings.
Both the .rspec and --require options have existed since 2011 at least (which is ages ago).
And, RSpec is especially not a tool for people needing training wheels - you want people to understand how RSpec works and what the options are, because you want people to know e.g. when and where to temporarily set the --seed option, how to change the formatter, switch on --fail-fast, use specific tags to work on a feature, etc.
The test environment also has to have a consistent configuration, so you do not want people tweaking the spec_helper file or the .rspec file (for the same reason).
In short: if it doesn't apply to every spec in the project, it shouldn't be in the spec_helper file. Which is why you should make sure it is included by every spec file. And the .rspec file is the best way to do that.
The only reason to not to switch to this is when the project is being actively maintained by many people (and any project wide change just creates annoyances by e.g. forcing people to rebase their work for no reason related to what they were working on).
Bundler fits into this category - to many people potentially working concurrently.
P.S. I also recommend using rspec --init on an empty project and checking out the generated config.

How can I stop Padrino putting compiled SASS in my public/ directory? Or should I?

I'm playing with Padrino, experimenting with a very minimal site at the moment with no DB and just a few HAML and SASS files under the app/ directory.
What I've noticed is that each time I render a page which links to a stylesheet that's defined in a .sass file, it compiles the stylesheet to .css and stores it under public/.
This is all very well, but I also have some static assets stored in public/, including images and some other hand-written .css files.
What this means is that my public/ directory becomes a mix of things I placed there and things compiled by Padrino. So, looking in there will show a bunch of .css files, some of which are compiled .sass files, and some of which are my actual primary static assets. This is confusing.
Is there a way I can stop Padrino (or Sinatra, or Rack, or whatever is doing it) from saving these compiled files during development, and keep my public/ clean?
Alternatively, can someone explain why what I'm asking for is a bad idea / by design / I should learn to love it instead? :-)
Thanks.
I don't know how to set the SASS settings for Padrino, I had a look and couldn't find anything helpful either. I would feel a bit nervous about running it this way too, it could easily get confusing and unhelpful, and what if the asset names clash?
What you could do is not add SASS in via Padrino, and then run it yourself either via the --watch switch or via something like Guard. That way you can also specify different subfolders within the public directory (images/css/js etc), which is what I do (although it does mean you need to remember to add the subfolder as part of the path when describing links). The app doesn't even need to know you're using SASS, and precompilation, when it's this simple, is surely better than the kind of compilation on demand that you've got at the moment (IMO).
You might try the Padrino mailing list for help with the settings.
Using the padrino-sprockets gems I also wanted to change the default /public/stylesheets directory to /assets/stylesheets where sprockets pick them up. I found that my padrino project genereated with the -c sass option had a /lib/sass_plugin.rb file with the following:
# Enables support for SASS template reloading for rack.
# Store SASS files by default within 'app/stylesheets/sass'
# See http://nex-3.com/posts/88-sass-supports-rack for more details.
module SassInitializer
def self.registered(app)
require 'sass/plugin/rack'
Sass::Plugin.options[:template_location] = File.join(Padrino.root, "app/stylesheets")
Sass::Plugin.options[:css_location] = File.join(Padrino.root, "public/stylesheets")
app.use Sass::Plugin::Rack
end
end
Editing the :css_location path and restarting Padrino did the trick!

How do I get my ruby source in the load path when invoking with thin?

I'm playing around with a combination of Thin, Sinatra and Bundler. I'm trying to understand how I get Thin to include the path to my source code in the load path? I have looked for introductory tutorials to this setup, but none of them seem to answer my question.
Mucking around with the rackup file or Thin config file feels wrong. Assume I have a directory structure with something like:
bin/my-application-entry.rb # The entry point to my sinatra application
lib/myapp/mylibs.rb
thin/config.ru # rackup config
thin/dev.yaml # thin config
Gemfile # for my dependencies
The contents of the rackup file is essentially
require 'sinatra'
# I'd like to require 'my-application-entry' around here somewhere (I think?)
run Sinatra.application
I invoke the application with
thin -C thin/dev.yaml -R thin/config.ru start
I noticed that thin takes a command-line argument to require a specific library, but surely there is a better place where you can define all the load paths?
So my question is really, how do I tell thin/rack/bundler which directories to include? (such as bin/ and lib/)
Edit: For clarity, I'd really like to know how this is generally done with Thin specifically. I am reluctant to modify $: in my main application, but if I am forced to use $:, where is the best place (in a Thin/Rack/Sinatra context) to do so?
$: is a global variable describing the load path, represented as an array. You can add ".", then if you care, eliminate duplicates, as follows:
$:.unshift(".").uniq!
Or you can push it to the end of the list:
$:.push(".").uniq!
It's often omitted by default because it's a potential security hazard.
I'm wondering the same thing. I'll tell you what I'm doing and try to justify it. Perhaps in the process of writing this, I'll have figured something out.
I have decided, for now, to add to $LOAD_PATH in config.ru, because I'm using config.ru as the entry point of my application. I can get away with this because I intend to leave this file in the root of the project. I don't like making that assumption, but it seems pretty safe for now. Of course, I'll leave a comment saying "Ew. Assumes that this file is the only entry point of the application and that it will always be in the root of the project."
I chose this because I want to add to $LOAD_PATH as high up in the call stack as possible (Dependency Inversion Principle), but doing so in the commands that run the app (Procfile running thin in production; command line running shotgun in development) duplicates the directories that I want to add to the load path. Do I classify this duplication as essential (worth removing) or coincidental (worth duplicating)? For now, it looks like an essential aspect of the app, at least as I've decided to organise it, because the app integrates the various services into a single request/response/routing engine. Also, config.ru describes the app, so it makes sense to treat it as the app.
If the situation changes and I notice that I want a different $LOAD_PATH in development than in production, then I'll move the directories up the call stack into the command that runs config.ru.
I feel comfortable with this choice, not because I consider it "the right choice", but because I think I know how and why I'd change my mind. Good enough for me.
I hope this helps.

Resources