|
# Rake spec tasks for engines |
|
# =========================== |
|
# |
|
# Dependencies: |
|
# - rails 3.2+ |
|
# - rspec-rails |
|
# - factory-girl |
|
# |
|
# Scenario: |
|
# - You have a Rails application with several engines. |
|
# - You have all the engines in the same directory within the app. |
|
# - You have properly configured your spec_helper to use rspec-rails and factory-girl |
|
# |
|
# Motivation: |
|
# - You don't want to use/setup a dummy app to test each engine |
|
# - You want to be able to run the specs for the engines separatedly but in the same env |
|
# |
|
# Solution: |
|
# Dynamically based on the folder/files structure add a Rake task to: |
|
# - Run all the specs of the host app, and all the engines |
|
# 'rake spec:all' |
|
# - Run all the specs of a specific engine |
|
# 'rake spec:engine_name |
|
# - Run all the specs of a certain type from an engine |
|
# 'rake spec:engine_name:spec_type |
|
# |
|
# Example: |
|
# For an engine located in '/engines/engine_name/special_category' |
|
# The rake tasks should look like: |
|
# - To run all the specs |
|
# rake spec:engine_name:special_category |
|
# - To run only the models specs |
|
# rake spec:engine_name:special_category:models |
|
# - To run only the controllers specs |
|
# rake spec:engine_name:special_category:models |
|
# - To run any other spec type specs |
|
# rake spec:engine_name:special-category:any_other_folder_name |
|
# |
|
# Notes: |
|
# * The specs should be in a folder named 'spec/' in the engine root folder |
|
# * The factories should be in the 'spec/' directory, inside a folder named 'factories/' |
|
# * Use 'rake -T' to check all the rake tasks |
|
# * spec_helper should be placed at "#{Rails.root}/spec/spec_helper.rb" |
|
# * In order for the rake task to be generated, the spec folder should contain files |
|
# ending with '_spec' |
|
# |
|
# Tips: |
|
# To configure RSpec + Factory Girl + Capybara here is a blogpost from @BRIAN LANDAU |
|
# http://viget.com/extend/rails-engine-testing-with-rspec-capybara-and-factorygirl |
|
|
|
spec_prereq = Rails.configuration.generators.options[:rails][:orm] == :active_record ? "test:prepare" : :noop |
|
task :noop do; end |
|
|
|
def absolute_rails_path(*segments) |
|
# Rails root path |
|
root = Rails.application.root |
|
root.join(*segments).to_s |
|
end |
|
|
|
def absolute_engine_path(*segments) |
|
absolute_rails_path(*(["engines"] + segments)) |
|
end |
|
|
|
def absolute_engine_factories_path(engine_path) |
|
absolute_engine_path(engine_path,'spec', "factories", "**", "*.rb") |
|
end |
|
|
|
namespace :spec do |
|
# One task to run them all |
|
desc "Run specs from the host app and the engines" |
|
RSpec::Core::RakeTask.new(:all => spec_prereq) do |t| |
|
t.rspec_opts = "-r ./spec/spec_helper.rb" |
|
t.pattern = [ |
|
absolute_rails_path("spec", "**", "*_spec.rb"), |
|
absolute_rails_path("spec", "factories", "**", "*_spec.rb"), |
|
absolute_engine_path("**", "*_spec.rb"), |
|
absolute_engine_path("**","factories", "**", "*.rb") |
|
] |
|
end |
|
|
|
def engine_types(engine_path) |
|
# Path to match all the available spec types from within a specific engine |
|
# spec types => controllers, models, helpers, etc |
|
engine_type_dirs = absolute_engine_path(engine_path, '**', 'spec', '**', '*_spec.rb') |
|
|
|
# Get all the unique engine spec types paths |
|
dirs = Dir[engine_type_dirs].map { |f| f.sub(/.*?\/spec\/(\w+)\/.*/, '\\1') }.uniq |
|
|
|
# Creating a hash with a task-like name as key and |
|
# its corresponding path as value |
|
Hash[dirs.map { |d| [d.split('/').last, d] }] |
|
end |
|
|
|
def engines |
|
# Path to match all the engine directories with a 'spec/' directory |
|
# that contains files ending with _spec |
|
engine_dirs = absolute_engine_path('**', 'spec', '**', '*_spec.rb') |
|
|
|
# Getting all the different engine paths |
|
dirs = Dir[engine_dirs].map { |f| f.sub(/.*?\/engines\/(.*?)\/spec.*/, '\\1') }.uniq |
|
|
|
# Creating a hash with a task-like name as key and |
|
# its corresponding path as value |
|
Hash[dirs.map { |d| [d.gsub('/',':'), d] }] |
|
end |
|
|
|
# For each engine we will create different rake tasks |
|
engines.each do |engine, engine_path| |
|
# A task to run all the engine specs at once |
|
# sample call for an engine wich path is '/vendor/special/api' |
|
# should be 'rake spec:vendor:special:api' |
|
desc "Run the specs for the engine #{engine}" |
|
RSpec::Core::RakeTask.new(engine => spec_prereq) do |t| |
|
t.rspec_opts = "-r ./spec/spec_helper.rb" |
|
|
|
# If there are factories, they will be picked up too |
|
t.pattern = [ |
|
absolute_engine_factories_path(engine_path), |
|
absolute_engine_path(engine_path, "**", "*_spec.rb") |
|
] |
|
end |
|
|
|
# For each engine we also create a namespace |
|
namespace engine do |
|
|
|
# For each type of specs from within the engine, we create another task |
|
# to run only those |
|
engine_types(engine_path).each do |type, type_path| |
|
|
|
desc "Run the #{type} specs from the #{engine} engine" |
|
RSpec::Core::RakeTask.new(type => spec_prereq) do |t| |
|
t.rspec_opts = "-r ./spec/spec_helper.rb" |
|
|
|
# If there are factories, they will be picked up too |
|
t.pattern = [ |
|
absolute_engine_factories_path(engine_path), |
|
absolute_engine_path(engine_path,"spec", type_path, "**", "*_spec.rb") |
|
] |
|
end |
|
end |
|
end |
|
end |
|
end |