Skip to content

Commit

Permalink
Merge branch 'jherdman'
Browse files Browse the repository at this point in the history
* jherdman:
  Don't incur the wrath of Ezra
  changes to the global_helpers should run every helper spec too
  Clean up a few stray issues
  General MerbRspec clean up
  MerbRspec has gastric bipass
  Some things for consistency
  Clean up major governing file specs
  Clean up controller specs
  Clean up view specs mapping
  Clean up helper specs and introduce a handy method for specifying the location of a given spec
  A much more concise mapping for specs
  Remove baked-in support for fixtures. This is between you and your ORM
  Better handling of stuff in /lib
  Clean up handle_results
  Add the DRY and semantically friendly 'all_specs' method
  Add exceptions for SCM directories and custom autotest mappings
  • Loading branch information
michaelklishin committed May 14, 2008
2 parents 519f1b8 + 92d2c53 commit 773147f
Showing 1 changed file with 58 additions and 115 deletions.
173 changes: 58 additions & 115 deletions merb-gen/app_generators/merb/templates/autotest/merb_rspec.rb
Expand Up @@ -3,104 +3,81 @@

class RspecCommandError < StandardError; end

# This class maps your application's structure so Autotest can understand what
# specs to run when files change.
#
# Fixtures are _not_ covered by this class. If you change a fixture file, you
# will have to run your spec suite manually, or, better yet, provide your own
# Autotest map explaining how your fixtures are set up.
class Autotest::MerbRspec < Autotest

# +model_tests_dir+:: the directory to find model-centric tests
# +controller_tests_dir+:: the directory to find controller-centric tests
# +view_tests_dir+:: the directory to find view-centric tests
# +fixtures_dir+:: the directory to find fixtures in
attr_accessor :model_tests_dir, :controller_tests_dir, :view_tests_dir, :fixtures_dir

def initialize
super

initialize_test_layout

# Ignore any happenings in these directories
add_exception %r%^\./(?:doc|log|public|tmp)%

# Ignore SCM directories and custom Autotest mappings
%w[.svn .hg .git .autotest].each { |exception| add_exception(exception) }

# Ignore any mappings that Autotest may have already set up
clear_mappings

# Any changes to a file in the root of the 'lib' directory will run any
# model test with a corresponding name.
add_mapping %r%^lib\/.*\.rb% do |filename, _|
files_matching %r%#{model_test_for(filename)}$%
# Anything in /lib could have a spec anywhere, if at all. So, look for
# files with roughly the same name as the file in /lib
add_mapping %r%^lib\/(.*)\.rb% do |_, m|
files_matching %r%^spec\/#{m[1]}%
end

add_mapping %r%^spec/(spec_helper|shared/.*)\.rb$% do
files_matching %r%^spec/.*_spec\.rb$%
end

# Any changes to a fixture will run corresponding view, controller and
# model tests
add_mapping %r%^#{fixtures_dir}/(.*)s.yml% do |_, m|
[
model_test_for(m[1]),
controller_test_for(m[1]),
view_test_for(m[1])
]
all_specs
end

# Any change to a test or spec will cause it to be run
add_mapping %r%^spec/(unit|models|integration|controllers|views|functional)/.*rb$% do |filename, _|
# Changing a spec will cause it to run itself
add_mapping %r%^spec/.*\.rb$% do |filename, _|
filename
end

# Any change to a model will cause it's corresponding test to be run
add_mapping %r%^app/models/(.*)\.rb$% do |_, m|
model_test_for(m[1])
spec_for(m[1], 'model')
end

# Any change to the global helper will result in all view and controller
# Any change to global_helpers will result in all view and controller
# tests being run
add_mapping %r%^app/helpers/global_helpers.rb% do
files_matching %r%^spec/(views|functional|controllers)/.*_spec\.rb$%
add_mapping %r%^app/helpers/global_helpers\.rb% do
files_matching %r%^spec/(views|controllers|helpers)/.*_spec\.rb$%
end

# Any change to a helper will run it's corresponding view and controller
# tests, unless the helper is the global helper. Changes to the global
# helper run all view and controller tests.
add_mapping %r%^app/helpers/(.*)_helper(s)?.rb% do |_, m|
if m[1] == "global" then
files_matching %r%^spec/(views|functional|controllers)/.*_spec\.rb$%
else
[
view_test_for(m[1]),
controller_test_for(m[1])
]
end
# Any change to a helper will cause its spec to be run
add_mapping %r%^app/helpers/(.*)_helper(s)?\.rb% do |_, m|
spec_for(m[1], 'helper')
end

# Changes to views result in their corresponding view and controller test
# being run
# Changes to a view cause its spec to be run
add_mapping %r%^app/views/(.*)/% do |_, m|
[
view_test_for(m[1]),
controller_test_for(m[1])
]
spec_for(m[1], 'view')
end

# Changes to a controller result in its corresponding test being run. If
# Changes to a controller result in its corresponding spec being run. If
# the controller is the exception or application controller, all
# controller tests are run.
# controller specs are run.
add_mapping %r%^app/controllers/(.*)\.rb$% do |_, m|
if ["application", "exception"].include?(m[1])
files_matching %r%^spec/(controllers|views|functional)/.*_spec\.rb$%
files_matching %r%^spec/controllers/.*_spec\.rb$%
else
controller_test_for(m[1])
spec_for(m[1], 'controller')
end
end

# If a change is made to the router, run all controller and view tests
add_mapping %r%^config/router.rb$% do # FIX
files_matching %r%^spec/(controllers|views|functional)/.*_spec\.rb$%
# If a change is made to the router, run controller, view and helper specs
add_mapping %r%^config/router.rb$% do
files_matching %r%^spec/(controllers|views|helpers)/.*_spec\.rb$%
end

# If any of the major files governing the environment are altered, run
# everything
add_mapping %r%^spec/spec_helper.rb|config/(init|rack|environments/test.rb|database.yml)% do # FIX
files_matching %r%^spec/(unit|models|controllers|views|functional)/.*_spec\.rb$%
add_mapping %r%^config/(init|rack|environments/test).*\.rb|database\.yml% do
all_specs
end
end

Expand All @@ -109,39 +86,31 @@ def failed_results(results)
end

def handle_results(results)
@failures = failed_results(results)
@files_to_test = consolidate_failures @failures
unless $TESTING
if @files_to_test.empty?
hook :green
else
hook :red
end
end
@tainted = true unless @files_to_test.empty?
@failures = failed_results(results)
@files_to_test = consolidate_failures(@failures)
@files_to_test.empty? && !$TESTING ? hook(:green) : hook(:red)
@tainted = !@files_to_test.empty?
end

def consolidate_failures(failed)
filters = Hash.new { |h,k| h[k] = [] }
failed.each do |spec, failed_trace|
find_files.keys.select { |f| f =~ /spec\// }.each do |f|
if failed_trace =~ Regexp.new(f)
filters[f] << spec
break
end
if f = test_files_for(failed).find { |f| f =~ /spec\// }
filters[f] << spec
break
end
end
filters
end

def make_test_cmd(files_to_test)
def make_test_cmd(specs_to_runs)
[
ruby,
"-S",
spec_command,
add_options_if_present,
files_to_test.keys.flatten.join(' ')
].join(" ")
].join(' ')
end

def add_options_if_present
Expand All @@ -153,10 +122,10 @@ def add_options_if_present
# ~/.autotest to provide a different spec command then the default
# paths provided.
def spec_command(separator=File::ALT_SEPARATOR)
unless defined? @spec_command then
@spec_command = spec_commands.find { |cmd| File.exists? cmd }
unless defined?(@spec_command)
@spec_command = spec_commands.find { |cmd| File.exists?(cmd) }

raise RspecCommandError, "No spec command could be found!" unless @spec_command
raise RspecCommandError, "No spec command could be found" unless @spec_command

@spec_command.gsub!(File::SEPARATOR, separator) if separator
end
Expand All @@ -169,55 +138,29 @@ def spec_command(separator=File::ALT_SEPARATOR)
# * default spec bin/loader installed in Rubygems
# * any spec command found in PATH
def spec_commands
[ File.join(Config::CONFIG['bindir'], 'spec'), 'spec' ]
[File.join(Config::CONFIG['bindir'], 'spec'), 'spec']
end

private

# Determines the paths we can expect tests or specs to reside, as well as
# corresponding fixtures.
def initialize_test_layout
self.model_tests_dir = "spec/models"
self.controller_tests_dir = "spec/controllers"
self.view_tests_dir = "spec/views"
self.fixtures_dir = "spec/fixtures"
# Runs +files_matching+ for all specs
def all_specs
files_matching %r%^spec/.*_spec\.rb$%
end

# Given a filename and the test type, this method will return the
# corresponding test's or spec's name.
# Generates a path to some spec given its kind and the match from a mapping
#
# ==== Arguments
# +filename+<String>:: the file name of the model, view, or controller
# +kind_of_test+<Symbol>:: the type of test we that we should run
# match<String>:: the match from a mapping
# kind<String>:: the kind of spec that the match represents
#
# ==== Returns
# String:: the name of the corresponding test or spec
# String
#
# ==== Example
#
# > test_for("user", :model)
# => "user_test.rb"
# > test_for("login", :controller)
# => "login_controller_test.rb"
# > test_for("form", :view)
# => "form_view_spec.rb" # If you're running a RSpec-like suite
def test_for(filename, kind_of_test)
name = [filename]
name << kind_of_test.to_s if kind_of_test == :view
name << "spec"
return name.join("_") + ".rb"
# > spec_for('post', :view')
# => "spec/views/post_spec.rb"
def spec_for(match, kind)
File.join("spec", kind + 's', "#{match}_spec.rb")
end

def model_test_for(filename)
[model_tests_dir, test_for(filename, :model)].join("/")
end

def controller_test_for(filename)
[controller_tests_dir, test_for(filename, :controller)].join("/")
end

def view_test_for(filename)
[view_tests_dir, test_for(filename, :view)].join("/")
end

end

0 comments on commit 773147f

Please sign in to comment.