Module: MSpec

Defined in:
lib/mspec/matchers/include.rb,
lib/mspec/version.rb,
lib/mspec/runner/mspec.rb

Overview

Cannot override #include at the toplevel in MRI

Constant Summary collapse

VERSION =
SpecVersion.new "1.5.8"

Class Method Summary collapse

Class Method Details

.actions(action, *args) ⇒ Object



59
60
61
62
# File 'lib/mspec/runner/mspec.rb', line 59

def self.actions(action, *args)
  actions = retrieve(action)
  actions.each { |obj| obj.send action, *args } if actions
end

.clear_currentObject

Sets the toplevel ContextState to nil.



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

def self.clear_current
  store :current, nil
end

.clear_expectationsObject

Resets the flag that an expectation has been encountered in an example.



224
225
226
# File 'lib/mspec/runner/mspec.rb', line 224

def self.clear_expectations
  store :expectations, false
end

.clear_modesObject

Clears all registered modes.



141
142
143
# File 'lib/mspec/runner/mspec.rb', line 141

def self.clear_modes
  store :modes, []
end

.currentObject

Returns the toplevel ContextState.



88
89
90
# File 'lib/mspec/runner/mspec.rb', line 88

def self.current
  retrieve :current
end

.delete_tag(tag) ⇒ Object

Deletes tag from the tag file if it exists. Returns true if the tag is deleted, false otherwise. Deletes the tag file if it is empty.



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/mspec/runner/mspec.rb', line 294

def self.delete_tag(tag)
  deleted = false
  pattern = /#{tag.tag}.*#{Regexp.escape(tag.escape(tag.description))}/
  file = tags_file
  if File.exist? file
    lines = IO.readlines(file)
    File.open(file, "w") do |f|
      lines.each do |line|
        unless pattern =~ line.chomp
          f.puts line unless line.empty?
        else
          deleted = true
        end
      end
    end
    File.delete file unless File.size? file
  end
  return deleted
end

.delete_tagsObject

Removes the tag file associated with a spec file.



315
316
317
318
# File 'lib/mspec/runner/mspec.rb', line 315

def self.delete_tags
  file = tags_file
  File.delete file if File.exists? file
end

.describe(mod, options = nil, &block) ⇒ Object



28
29
30
31
32
33
34
35
36
# File 'lib/mspec/runner/mspec.rb', line 28

def self.describe(mod, options=nil, &block)
  state = ContextState.new mod, options
  state.parent = current

  MSpec.register_current state
  state.describe(&block)

  state.process unless state.shared? or current
end

.exit_codeObject

Retrieves the stored exit code.



108
109
110
# File 'lib/mspec/runner/mspec.rb', line 108

def self.exit_code
  retrieve(:exit).to_i
end

.expectationObject

Records that an expectation has been encountered in an example.



214
215
216
# File 'lib/mspec/runner/mspec.rb', line 214

def self.expectation
  store :expectations, true
end

.expectation?Boolean

Returns true if an expectation has been encountered

Returns:

  • (Boolean)


219
220
221
# File 'lib/mspec/runner/mspec.rb', line 219

def self.expectation?
  retrieve :expectations
end

.filesObject



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/mspec/runner/mspec.rb', line 44

def self.files
  return unless files = retrieve(:files)

  shuffle files if randomize?
  files.each do |file|
    @env = Object.new
    @env.extend MSpec

    store :file, file
    actions :load
    protect("loading #{file}") { Kernel.load file }
    actions :unload
  end
end

.include(*expected) ⇒ Object



28
29
30
# File 'lib/mspec/matchers/include.rb', line 28

def include(*expected)
  IncludeMatcher.new(*expected)
end

.mode?(mode) ⇒ Boolean

Returns true if mode is registered.

Returns:

  • (Boolean)


146
147
148
# File 'lib/mspec/runner/mspec.rb', line 146

def self.mode?(mode)
  retrieve(:modes).include? mode
end

.processObject



38
39
40
41
42
# File 'lib/mspec/runner/mspec.rb', line 38

def self.process
  actions :start
  files
  actions :finish
end

.protect(location, &block) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/mspec/runner/mspec.rb', line 64

def self.protect(location, &block)
  begin
    @env.instance_eval(&block)
    return true
  rescue SystemExit
    raise
  rescue Exception => exc
    register_exit 1
    actions :exception, ExceptionState.new(current && current.state, location, exc)
    return false
  end
end

.randomize(flag = true) ⇒ Object



195
196
197
# File 'lib/mspec/runner/mspec.rb', line 195

def self.randomize(flag=true)
  @randomize = flag
end

.randomize?Boolean

Returns:

  • (Boolean)


199
200
201
# File 'lib/mspec/runner/mspec.rb', line 199

def self.randomize?
  @randomize == true
end

.read_tags(keys) ⇒ Object

Returns a list of tags matching any tag string in keys based on the return value of keys.include?("tag_name")



248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/mspec/runner/mspec.rb', line 248

def self.read_tags(keys)
  tags = []
  file = tags_file
  if File.exist? file
    File.open(file, "r") do |f|
      f.each_line do |line|
        line.chomp!
        next if line.empty?
        tag = SpecTag.new line.chomp
        tags << tag if keys.include? tag.tag
      end
    end
  end
  tags
end

.register(symbol, action) ⇒ Object

This method is used for registering actions that are run at particular points in the spec cycle:

:start        before any specs are run
:load         before a spec file is loaded
:enter        before a describe block is run
:before       before a single spec is run
:expectation  before a 'should', 'should_receive', etc.
:example      after an example block is run, passed the block
:exception    after an exception is rescued
:after        after a single spec is run
:leave        after a describe block is run
:unload       after a spec file is run
:finish       after all specs are run

Objects registered as actions above should respond to a method of the same name. For example, if an object is registered as a :start action, it should respond to a #start method call.

Additionally, there are two “action” lists for filtering specs:

:include  return true if the spec should be run
:exclude  return true if the spec should NOT be run


182
183
184
185
186
187
# File 'lib/mspec/runner/mspec.rb', line 182

def self.register(symbol, action)
  unless value = retrieve(symbol)
    value = store symbol, []
  end
  value << action unless value.include? action
end

.register_current(state) ⇒ Object

Sets the toplevel ContextState to state.



78
79
80
# File 'lib/mspec/runner/mspec.rb', line 78

def self.register_current(state)
  store :current, state
end

.register_exit(code) ⇒ Object

Stores the exit code used by the runner scripts.



103
104
105
# File 'lib/mspec/runner/mspec.rb', line 103

def self.register_exit(code)
  store :exit, code
end

.register_files(files) ⇒ Object

Stores the list of files to be evaluated.



113
114
115
# File 'lib/mspec/runner/mspec.rb', line 113

def self.register_files(files)
  store :files, files
end

.register_mode(mode) ⇒ Object

Registers an operating mode. Modes recognized by MSpec:

:pretend - actions execute but specs are not run
:verify - specs are run despite guards and the result is
          verified to match the expectation of the guard
:report - specs that are guarded are reported
:unguarded - all guards are forced off


135
136
137
138
# File 'lib/mspec/runner/mspec.rb', line 135

def self.register_mode(mode)
  modes = retrieve :modes
  modes << mode unless modes.include? mode
end

.register_shared(state) ⇒ Object

Stores the shared ContextState keyed by description.



93
94
95
# File 'lib/mspec/runner/mspec.rb', line 93

def self.register_shared(state)
  @shared[state.to_s] = state
end

.register_tags_patterns(patterns) ⇒ Object

Stores one or more substitution patterns for transforming a spec filename into a tags filename, where each pattern has the form:

[Regexp, String]

See also tags_file.



124
125
126
# File 'lib/mspec/runner/mspec.rb', line 124

def self.register_tags_patterns(patterns)
  store :tags_patterns, patterns
end

.retrieve(symbol) ⇒ Object



150
151
152
# File 'lib/mspec/runner/mspec.rb', line 150

def self.retrieve(symbol)
  instance_variable_get :"@#{symbol}"
end

.retrieve_shared(desc) ⇒ Object

Returns the shared ContextState matching description.



98
99
100
# File 'lib/mspec/runner/mspec.rb', line 98

def self.retrieve_shared(desc)
  @shared[desc.to_s]
end

.shuffle(ary) ⇒ Object



203
204
205
206
207
208
209
210
211
# File 'lib/mspec/runner/mspec.rb', line 203

def self.shuffle(ary)
  return if ary.empty?

  size = ary.size
  size.times do |i|
    r = rand(size - i - 1)
    ary[i], ary[r] = ary[r], ary[i]
  end
end

.store(symbol, value) ⇒ Object



154
155
156
# File 'lib/mspec/runner/mspec.rb', line 154

def self.store(symbol, value)
  instance_variable_set :"@#{symbol}", value
end

.tags_fileObject

Transforms a spec filename into a tags filename by applying each substitution pattern in :tags_pattern. The default patterns are:

[%r(/spec/), '/spec/tags/'], [/_spec.rb$/, '_tags.txt']

which will perform the following transformation:

path/to/spec/class/method_spec.rb => path/to/spec/tags/class/method_tags.txt

See also register_tags_patterns.



238
239
240
241
242
243
244
# File 'lib/mspec/runner/mspec.rb', line 238

def self.tags_file
  patterns = retrieve(:tags_patterns) ||
             [[%r(spec/), 'spec/tags/'], [/_spec.rb$/, '_tags.txt']]
  patterns.inject(retrieve(:file).dup) do |file, pattern|
    file.gsub(*pattern)
  end
end

.unregister(symbol, action) ⇒ Object



189
190
191
192
193
# File 'lib/mspec/runner/mspec.rb', line 189

def self.unregister(symbol, action)
  if value = retrieve(symbol)
    value.delete action
  end
end

.write_tag(tag) ⇒ Object

Writes tag to the tag file if it does not already exist. Returns true if the tag is written, false otherwise.



277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/mspec/runner/mspec.rb', line 277

def self.write_tag(tag)
  string = tag.to_s
  file = tags_file
  path = File.dirname file
  FileUtils.mkdir_p path unless File.exist? path
  if File.exist? file
    File.open(file, "r") do |f|
      f.each_line { |line| return false if line.chomp == string }
    end
  end
  File.open(file, "a") { |f| f.puts string }
  return true
end

.write_tags(tags) ⇒ Object

Writes each tag in tags to the tag file. Overwrites the tag file if it exists.



266
267
268
269
270
271
272
273
# File 'lib/mspec/runner/mspec.rb', line 266

def self.write_tags(tags)
  file = tags_file
  path = File.dirname file
  FileUtils.mkdir_p path unless File.exist? path
  File.open(file, "w") do |f|
    tags.each { |t| f.puts t }
  end
end