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.14"

Class Method Summary collapse

Class Method Details

.actions(action, *args) ⇒ Object



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

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.



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

def self.clear_current
  store :current, nil
end

.clear_expectationsObject

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



240
241
242
# File 'lib/mspec/runner/mspec.rb', line 240

def self.clear_expectations
  store :expectations, false
end

.clear_modesObject

Clears all registered modes.



156
157
158
# File 'lib/mspec/runner/mspec.rb', line 156

def self.clear_modes
  store :modes, []
end

.currentObject

Returns the toplevel ContextState.



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

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.



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/mspec/runner/mspec.rb', line 310

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, "wb") 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.



331
332
333
334
# File 'lib/mspec/runner/mspec.rb', line 331

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

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



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

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.



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

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

.expectationObject

Records that an expectation has been encountered in an example.



230
231
232
# File 'lib/mspec/runner/mspec.rb', line 230

def self.expectation
  store :expectations, true
end

.expectation?Boolean

Returns true if an expectation has been encountered

Returns:

  • (Boolean)


235
236
237
# File 'lib/mspec/runner/mspec.rb', line 235

def self.expectation?
  retrieve :expectations
end

.filesObject



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

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

.guardObject

Guards can be nested, so a stack is necessary to know when we have exited the toplevel guard.



80
81
82
# File 'lib/mspec/runner/mspec.rb', line 80

def self.guard
  @guarded << true
end

.guarded?Boolean

Returns:

  • (Boolean)


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

def self.guarded?
  not @guarded.empty?
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)


161
162
163
# File 'lib/mspec/runner/mspec.rb', line 161

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

.processObject



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

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

.protect(location, &block) ⇒ Object



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

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



211
212
213
# File 'lib/mspec/runner/mspec.rb', line 211

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

.randomize?Boolean

Returns:

  • (Boolean)


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

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")



264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/mspec/runner/mspec.rb', line 264

def self.read_tags(keys)
  tags = []
  file = tags_file
  if File.exist? file
    File.open(file, "rb") 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
:add          while a describe block is adding examples to run later
: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


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

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.



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

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

.register_exit(code) ⇒ Object

Stores the exit code used by the runner scripts.



118
119
120
# File 'lib/mspec/runner/mspec.rb', line 118

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

.register_files(files) ⇒ Object

Stores the list of files to be evaluated.



128
129
130
# File 'lib/mspec/runner/mspec.rb', line 128

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


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

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.



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

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.



139
140
141
# File 'lib/mspec/runner/mspec.rb', line 139

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

.retrieve(symbol) ⇒ Object



165
166
167
# File 'lib/mspec/runner/mspec.rb', line 165

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

.retrieve_shared(desc) ⇒ Object

Returns the shared ContextState matching description.



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

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

.shuffle(ary) ⇒ Object



219
220
221
222
223
224
225
226
227
# File 'lib/mspec/runner/mspec.rb', line 219

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



169
170
171
# File 'lib/mspec/runner/mspec.rb', line 169

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.



254
255
256
257
258
259
260
# File 'lib/mspec/runner/mspec.rb', line 254

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

.unguardObject



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

def self.unguard
  @guarded.pop
end

.unregister(symbol, action) ⇒ Object



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

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.



293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/mspec/runner/mspec.rb', line 293

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, "rb") do |f|
      f.each_line { |line| return false if line.chomp == string }
    end
  end
  File.open(file, "ab") { |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.



282
283
284
285
286
287
288
289
# File 'lib/mspec/runner/mspec.rb', line 282

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