Class: ContextState

Inherits:
Object show all
Defined in:
lib/mspec/runner/context.rb

Overview

Holds the state of the describe block that is being evaluated. Every example (i.e. it block) is evaluated in a context, which may include state set up in before :each or before :all blocks.

– A note on naming: this is named ContextState rather than DescribeState because describe is the keyword in the DSL for refering to the context in which an example is evaluated, just as it refers to the example itself. ++

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mod, options = nil) ⇒ ContextState

Returns a new instance of ContextState.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/mspec/runner/context.rb', line 18

def initialize(mod, options=nil)
  @to_s = mod.to_s
  if options.is_a? Hash
    @options = options
  else
    @to_s += "#{".:#".include?(options[0,1]) ? "" : " "}#{options}" if options
    @options = { }
  end
  @options[:shared] ||= false

  @parsed   = false
  @before   = { :all => [], :each => [] }
  @after    = { :all => [], :each => [] }
  @pre      = {}
  @post     = {}
  @examples = []
  @parent   = nil
  @parents  = [self]
  @children = []

  @mock_verify         = lambda { Mock.verify_count }
  @mock_cleanup        = lambda { Mock.cleanup }
  @expectation_missing = lambda { raise ExpectationNotFoundError }
end

Instance Attribute Details

#childrenObject (readonly)

Returns the value of attribute children.



16
17
18
# File 'lib/mspec/runner/context.rb', line 16

def children
  @children
end

#examplesObject (readonly)

Returns the value of attribute examples.



16
17
18
# File 'lib/mspec/runner/context.rb', line 16

def examples
  @examples
end

#parentObject

Returns the value of attribute parent.



16
17
18
# File 'lib/mspec/runner/context.rb', line 16

def parent
  @parent
end

#parentsObject (readonly)

Returns the value of attribute parents.



16
17
18
# File 'lib/mspec/runner/context.rb', line 16

def parents
  @parents
end

#stateObject (readonly)

Returns the value of attribute state.



16
17
18
# File 'lib/mspec/runner/context.rb', line 16

def state
  @state
end

#to_sObject (readonly)

Returns the value of attribute to_s.



16
17
18
# File 'lib/mspec/runner/context.rb', line 16

def to_s
  @to_s
end

Instance Method Details

#after(what, &block) ⇒ Object

Records after(:each) and after(:all) blocks.



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

def after(what, &block)
  block ? @after[what].unshift(block) : @after[what]
end

#before(what, &block) ⇒ Object

Records before(:each) and before(:all) blocks.



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

def before(what, &block)
  block ? @before[what].push(block) : @before[what]
end

#child(child) ⇒ Object

Add the ContextState instance child to the list of nested describe blocks.



65
66
67
# File 'lib/mspec/runner/context.rb', line 65

def child(child)
  @children << child
end

#describe(&block) ⇒ Object

Evaluates the block and resets the toplevel ContextState to #parent.



100
101
102
103
104
# File 'lib/mspec/runner/context.rb', line 100

def describe(&block)
  @parsed = protect @to_s, block, false
  MSpec.register_current parent
  MSpec.register_shared self if shared?
end

#descriptionObject

Returns a description string generated from self and all parents



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

def description
  @description ||= parents.map { |p| p.to_s }.join(" ")
end

#filter_examplesObject

Removes filtered examples. Returns true if there are examples left to evaluate.



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

def filter_examples
  @examples.reject! { |ex| ex.filtered? }
  not @examples.empty?
end

#it(desc, &block) ⇒ Object

Creates an ExampleState instance for the block and stores it in a list of examples to evaluate unless the example is filtered.



95
96
97
# File 'lib/mspec/runner/context.rb', line 95

def it(desc, &block)
  @examples << ExampleState.new(self, desc, block)
end

#it_should_behave_like(desc) ⇒ Object

Injects the before/after blocks and examples from the shared describe block into this ContextState instance.



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/mspec/runner/context.rb', line 113

def it_should_behave_like(desc)
  unless state = MSpec.retrieve_shared(desc)
    raise Exception, "Unable to find shared 'describe' for #{desc}"
  end

  state.examples.each { |ex| ex.context = self; @examples << ex }
  state.before(:all).each { |b| before :all, &b }
  state.before(:each).each { |b| before :each, &b }
  state.after(:each).each { |b| after :each, &b }
  state.after(:all).each { |b| after :all, &b }
end

#post(what) ⇒ Object

Returns a list of all after(what) blocks from self and any parents. The list is in reverse order. In other words, the blocks defined in inner describes are in the list before those defined in outer describes, and in a particular describe block those defined later are in the list before those defined earlier.



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

def post(what)
  @post[what] ||= parents.inject([]) { |l, s| l.unshift(*s.after(what)) }
end

#pre(what) ⇒ Object

Returns a list of all before(what) blocks from self and any parents.



70
71
72
# File 'lib/mspec/runner/context.rb', line 70

def pre(what)
  @pre[what] ||= parents.inject([]) { |l, s| l.push(*s.before(what)) }
end

#processObject

Evaluates the examples in a ContextState. Invokes the MSpec events for :enter, :before, :after, :leave.



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/mspec/runner/context.rb', line 143

def process
  MSpec.register_current self

  if @parsed and filter_examples
    MSpec.shuffle @examples if MSpec.randomize?
    MSpec.actions :enter, description

    if protect "before :all", pre(:all)
      @examples.each do |state|
        @state  = state
        example = state.example
        MSpec.actions :before, state

        if protect "before :each", pre(:each)
          MSpec.clear_expectations
          if example
            passed = protect nil, example
            MSpec.actions :example, state, example
            protect nil, @expectation_missing unless MSpec.expectation? or not passed
          end
          protect "after :each", post(:each)
          protect "Mock.verify_count", @mock_verify
        end

        protect "Mock.cleanup", @mock_cleanup
        MSpec.actions :after, state
        @state = nil
      end
      protect "after :all", post(:all)
    else
      protect "Mock.cleanup", @mock_cleanup
    end

    MSpec.actions :leave
  end

  MSpec.register_current nil
  children.each { |child| child.process }
end

#protect(what, blocks, check = true) ⇒ Object

Evaluates each block in blocks using the MSpec.protect method so that exceptions are handled and tallied. Returns true and does NOT evaluate any blocks if check is true and MSpec.pretend_mode? is true.



129
130
131
132
# File 'lib/mspec/runner/context.rb', line 129

def protect(what, blocks, check=true)
  return true if check and MSpec.pretend_mode?
  Array(blocks).all? { |block| MSpec.protect what, &block }
end

#shared?Boolean

Returns true if this is a shared ContextState. Essentially, when created with: describe “Something”, :shared => true { … }

Returns:

  • (Boolean)


45
46
47
# File 'lib/mspec/runner/context.rb', line 45

def shared?
  return @options[:shared]
end