GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Fork of wycats/merb-core
Description: Merb Core: All you need. None you don't.
Homepage: http://www.merbivore.com
Clone URL: git://github.com/auser/merb-core.git
commit  496a43b7d0b1efabc8324e88383a7cc188a5c5d5
tree    4bd883b96948dc816d7c5c659e7bcd6125fcd0be
parent  72be5800e7b715ea544ba70f06129b29c0d7a6f1
merb-core / autotest / merbsource_rspec.rb
100644 132 lines (105 sloc) 4.246 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
require 'autotest'
# require File.dirname(__FILE__) + '/textmate'
 
$VERBOSE = false
  
# cloned from Rspec's autotest settings, but modified
# to cope w/ Merb's specs directory layout
 
# ==== Merb Source Autotest Rules
# 1. Updating a spec reruns that spec
# 2. Updating a spec_helper reruns all specs at that level and below
# 3. Updating a file under controller (i.e. abstract_controller.rb)
# reruns all the specs under (public|private)/abstract_controller
# 4. Updating a file under controller/mixins (e.g. render)
# reruns all specs under
# (public|private)/(abstract_controller|controller)/render_spec.rb
# 5. Updating a file directly under merb_core (e.g. core_ext.rb)
# reruns all the specs under spec/(public|private)/core_ext
# 6. Updating merb.rb reruns all specs
 
class RspecCommandError < StandardError; end
 
class Autotest::MerbsourceRspec < Autotest
  
  Autotest.add_hook :initialize do |at|
    %w{.git}.each {|exception| at.exceptions.push exception}
  end
  
  require 'ruby-debug'
 
  Autotest.add_hook :run do |at|
    # See above for human-readable descriptions of these rules
      # 1 above
      at.add_mapping(%r{^spec/.*_spec\.rb$}) { |filename, _| filename}
 
      # 2 above
      at.add_mapping(%r{^spec/(.*)/spec_helper\.rb$}) { |_, m| at.files_matching %r{^spec/#{m[1]}/.*_spec\.rb$} }
 
      # 3 above
      at.add_mapping(%r{^lib/merb_core/controller/([^/]*)\.rb$}) { |_, m| at.files_matching %r{^spec\/(public|private)\/#{m[1]}\/.*_spec\.rb} }
 
      # 4 above
      at.add_mapping(%r{^lib/merb_core/controller/mixins/([^/]*)\.rb$}) { |_, m| at.files_matching %r{^spec/(public|private)/(abstract_)?controller/#{m[1]}_spec\.rb} }
 
      # 5 above
      at.add_mapping(%r{^lib/merb_core/([^/]*)\.rb$}) { |_, m| at.files_matching %r{^spec/(public|private)/#{m[1]}/.*_spec\.rb} }
 
      # 6 above
      at.add_mapping(%r{^lib/merb\.rb$}) { at.files_matching %r{^spec/[^/]*_spec\.rb$} }
 
  end
  
  def initialize(kernel = Kernel, separator = File::SEPARATOR, alt_separator = File::ALT_SEPARATOR) # :nodoc:
    super() # need parens so that Ruby doesn't pass our args
    # to the superclass version which takes none..
    
    @kernel, @separator, @alt_separator = kernel, separator, alt_separator
    @spec_command = spec_command
  end
  
  attr_accessor :failures
  
  def tests_for_file(filename)
    super.select { |f| @files.has_key? f }
  end
  
  alias :specs_for_file :tests_for_file
  
  def failed_results(results)
    results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m)
  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?
  end
  
  def consolidate_failures(failed)
    filters = Hash.new { |h,k| h[k] = [] }
    failed.each do |spec, failed_trace|
      @files.keys.select { |f| f =~ /spec\// }.each do |f|
        if failed_trace =~ Regexp.new(f)
          filters[f] << spec
          break
        end
      end
    end
    filters
  end
  
  def make_test_cmd(files_to_test)
    "#{ruby} -S #{@spec_command} #{test_cmd_options} #{files_to_test.keys.flatten.join(' ')}"
  end
  
  def test_cmd_options
    '-O specs/spec.opts' if File.exist?('specs/spec.opts')
  end
  
  # Finds the proper spec command to use. Precendence
  # is set in the lazily-evaluated method spec_commands. Alias + Override
  # that in ~/.autotest to provide a different spec command
  # then the default paths provided.
  def spec_command
    if cmd = spec_commands.detect { |c| File.exist? c }
      @alt_separator ? (cmd.gsub @separator, @alt_separator) : cmd
    else
      raise RspecCommandError, 'No spec command could be found!'
    end
  end
  
  # Autotest will look for spec commands in the following
  # locations, in this order:
  #
  # * bin/spec
  # * default spec bin/loader installed in Rubygems
  def spec_commands
    if (spec = `which spec`.chomp) && !spec.empty?
      return [spec]
    end
    [File.join('bin', 'spec'),
     File.join(Config::CONFIG['bindir'], 'spec')]
  end
end