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.



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

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.



13
14
15
# File 'lib/mspec/runner/context.rb', line 13

def children
  @children
end

#examplesObject (readonly)

Returns the value of attribute examples.



13
14
15
# File 'lib/mspec/runner/context.rb', line 13

def examples
  @examples
end

#parentObject

Returns the value of attribute parent.



13
14
15
# File 'lib/mspec/runner/context.rb', line 13

def parent
  @parent
end

#parentsObject (readonly)

Returns the value of attribute parents.



13
14
15
# File 'lib/mspec/runner/context.rb', line 13

def parents
  @parents
end

#stateObject (readonly)

Returns the value of attribute state.



13
14
15
# File 'lib/mspec/runner/context.rb', line 13

def state
  @state
end

#to_sObject (readonly)

Returns the value of attribute to_s.



13
14
15
# File 'lib/mspec/runner/context.rb', line 13

def to_s
  @to_s
end

Instance Method Details

#after(what, &block) ⇒ Object

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



86
87
88
# File 'lib/mspec/runner/context.rb', line 86

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

#before(what, &block) ⇒ Object

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



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

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.



62
63
64
# File 'lib/mspec/runner/context.rb', line 62

def child(child)
  @children << child
end

#describe(&block) ⇒ Object

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



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

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



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

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.



133
134
135
136
# File 'lib/mspec/runner/context.rb', line 133

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.



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

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.



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/mspec/runner/context.rb', line 110

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.



76
77
78
# File 'lib/mspec/runner/context.rb', line 76

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.



67
68
69
# File 'lib/mspec/runner/context.rb', line 67

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.



140
141
142
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
# File 'lib/mspec/runner/context.rb', line 140

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.mode?(:pretend) is true.



126
127
128
129
# File 'lib/mspec/runner/context.rb', line 126

def protect(what, blocks, check=true)
  return true if check and MSpec.mode? :pretend
  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)


42
43
44
# File 'lib/mspec/runner/context.rb', line 42

def shared?
  return @options[:shared]
end