Class: MSpecScript

Inherits:
Object show all
Defined in:
lib/mspec/utils/script.rb

Overview

MSpecScript provides a skeleton for all the MSpec runner scripts.

Direct Known Subclasses

MSpecCI, MSpecMain, MSpecRun, MSpecTag

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMSpecScript

Returns a new instance of MSpecScript


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/mspec/utils/script.rb', line 40

def initialize
  config[:formatter] = nil
  config[:includes]  = []
  config[:excludes]  = []
  config[:patterns]  = []
  config[:xpatterns] = []
  config[:tags]      = []
  config[:xtags]     = []
  config[:profiles]  = []
  config[:xprofiles] = []
  config[:atags]     = []
  config[:astrings]  = []
  config[:ltags]     = []
  config[:abort]     = true
end

Class Method Details

.configObject

Returns the config object. Maintained at the class level to easily enable simple config files. See the class method set.


10
11
12
13
14
15
# File 'lib/mspec/utils/script.rb', line 10

def self.config
  @config ||= {
    :path => ['.', 'spec'],
    :config_ext => '.mspec'
  }
end

.get(key) ⇒ Object

Gets the value of key from the config object. Simplifies getting values in a config file:

class MSpecScript
  set :a, 1
  set :b, 2
  set :c, get(:a) + get(:b)
end

36
37
38
# File 'lib/mspec/utils/script.rb', line 36

def self.get(key)
  config[key]
end

.mainObject

Instantiates an instance and calls the series of methods to invoke the script.


212
213
214
215
216
217
218
219
220
221
# File 'lib/mspec/utils/script.rb', line 212

def self.main
  $VERBOSE = nil unless ENV['OUTPUT_WARNINGS']
  script = new
  script.load_default
  script.try_load '~/.mspecrc'
  script.options
  script.signals
  script.register
  script.run
end

.set(key, value) ⇒ Object

Associates value with key in the config object. Enables simple config files of the form:

class MSpecScript
  set :target, "ruby"
  set :files, ["one_spec.rb", "two_spec.rb"]
end

24
25
26
# File 'lib/mspec/utils/script.rb', line 24

def self.set(key, value)
  config[key] = value
end

Instance Method Details

#configObject

Returns the config object maintained by the instance's class. See the class methods set and config.


58
59
60
# File 'lib/mspec/utils/script.rb', line 58

def config
  MSpecScript.config
end

#custom_options(options) ⇒ Object

Callback for enabling custom options. This version is a no-op. Provide an implementation specific version in a config file. Called by #options after the MSpec-provided options are added.


106
107
108
# File 'lib/mspec/utils/script.rb', line 106

def custom_options(options)
  options.doc "   No custom options registered"
end

#custom_registerObject

Callback for enabling custom actions, etc. This version is a no-op. Provide an implementation specific version in a config file. Called by #register.


139
140
# File 'lib/mspec/utils/script.rb', line 139

def custom_register
end

#entries(partial) ⇒ Object

Attempts to resolve partial as a file or directory name in the following order:

1. +partial+
2. +partial+ + "_spec.rb"
3. <tt>File.join(config[:prefix], partial)</tt>
4. <tt>File.join(config[:prefix], partial + "_spec.rb")</tt>

If it is a file name, returns the name as an entry in an array. If it is a directory, returns all *_spec.rb files in the directory and subdirectories.

If unable to resolve partial, Kernel.abort is called.


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/mspec/utils/script.rb', line 167

def entries(partial)
  file = partial + "_spec.rb"
  patterns = [partial, file]
  if config[:prefix]
    patterns << File.join(config[:prefix], partial)
    patterns << File.join(config[:prefix], file)
  end

  patterns.each do |pattern|
    expanded = File.expand_path(pattern)
    if File.file?(expanded)
      return [expanded]
    elsif File.directory?(expanded)
      return Dir["#{expanded}/**/*_spec.rb"].sort
    end
  end

  abort "Could not find spec file #{partial}"
end

#files(list) ⇒ Object

Resolves each entry in list to a set of files.

If the entry has a leading '^' character, the list of files is subtracted from the list of files accumulated to that point.

If the entry has a leading ':' character, the corresponding key is looked up in the config object and the entries in the value retrieved are processed through #entries.


195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/mspec/utils/script.rb', line 195

def files(list)
  list.inject([]) do |files, item|
    case item[0]
    when ?^
      files -= entries(item[1..-1])
    when ?:
      key = item[1..-1].to_sym
      files += files(Array(config[key]))
    else
      files += entries(item)
    end
    files
  end
end

#load(target) ⇒ Object


83
84
85
# File 'lib/mspec/utils/script.rb', line 83

def load(target)
  try_load(target) or abort "Could not load config file #{target}"
end

#load_defaultObject

Attempts to load a default config file. First tries to load 'default.mspec'. If that fails, attempts to load a config file name constructed from the value of RUBY_ENGINE and the first two numbers in RUBY_VERSION. For example, on MRI 1.8.6, the file name would be 'ruby.1.8.mspec'.


92
93
94
95
96
97
98
99
100
101
# File 'lib/mspec/utils/script.rb', line 92

def load_default
  try_load 'default.mspec'

  if Object.const_defined?(:RUBY_ENGINE)
    engine = RUBY_ENGINE
  else
    engine = 'ruby'
  end
  try_load "#{engine}.#{SpecGuard.ruby_version}.mspec"
end

#registerObject

Registers all filters and actions.


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/mspec/utils/script.rb', line 111

def register
  if config[:formatter].nil?
    config[:formatter] = STDOUT.tty? ? SpinnerFormatter : @files.size < 50 ? DottedFormatter : FileFormatter
  end

  if config[:formatter]
    formatter = config[:formatter].new(config[:output])
    formatter.register
    MSpec.store :formatter, formatter
  end

  MatchFilter.new(:include, *config[:includes]).register    unless config[:includes].empty?
  MatchFilter.new(:exclude, *config[:excludes]).register    unless config[:excludes].empty?
  RegexpFilter.new(:include, *config[:patterns]).register   unless config[:patterns].empty?
  RegexpFilter.new(:exclude, *config[:xpatterns]).register  unless config[:xpatterns].empty?
  TagFilter.new(:include, *config[:tags]).register          unless config[:tags].empty?
  TagFilter.new(:exclude, *config[:xtags]).register         unless config[:xtags].empty?
  ProfileFilter.new(:include, *config[:profiles]).register  unless config[:profiles].empty?
  ProfileFilter.new(:exclude, *config[:xprofiles]).register unless config[:xprofiles].empty?

  DebugAction.new(config[:atags], config[:astrings]).register if config[:debugger]

  custom_register
end

#signalsObject

Sets up signal handlers. Only a handler for SIGINT is registered currently.


144
145
146
147
148
149
150
151
152
# File 'lib/mspec/utils/script.rb', line 144

def signals
  if config[:abort]
    Signal.trap "INT" do
      MSpec.actions :abort
      puts "\nProcess aborted!"
      exit! 1
    end
  end
end

#try_load(target) ⇒ Object

Returns true if the file was located in +config, possibly appending config. Returns false otherwise.


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/mspec/utils/script.rb', line 65

def try_load(target)
  names = [target]
  unless target[-6..-1] == config[:config_ext]
    names << target + config[:config_ext]
  end

  names.each do |name|
    return Kernel.load(name) if File.exist?(File.expand_path(name))

    config[:path].each do |dir|
      file = File.join dir, name
      return Kernel.load(file) if File.exist? file
    end
  end

  false
end