class XSpec::Context

Attributes

children[R]
evaluator[R]
name[R]
units_of_work[R]

Public Class Methods

__xspec_context() click to toggle source

A context includes the same DSL methods as the root level module, which enables the recursive creation.

# File lib/xspec/data_structures.rb, line 27
def __xspec_context; self; end
add_child_context(name = nil, opts = {}, &block) click to toggle source

Child contexts and units of work are typically added by the `describe` and `it` DSL methods respectively.

# File lib/xspec/data_structures.rb, line 77
def add_child_context(name = nil, opts = {}, &block)
  self.children << make(name, evaluator, &block)
end
add_memoized_method(name, &block) click to toggle source

Values of memoized methods are remembered only for the duration of a single unit of work. These are typically created using the `let` DSL method.

# File lib/xspec/data_structures.rb, line 135
def add_memoized_method(name, &block)
  define_method(name) do
    memoized[block] ||= instance_eval(&block)
  end
end
add_unit_of_work(name = nil, opts = {}, &block) click to toggle source
# File lib/xspec/data_structures.rb, line 81
def add_unit_of_work(name = nil, opts = {}, &block)
  self.units_of_work << UnitOfWork.new(name, block)
end
apply_evaluator!() click to toggle source

The assertion context should be applied after the user has had a chance to add their own methods. It needs to be last so that users can't clobber the assertion methods.

# File lib/xspec/data_structures.rb, line 57
def apply_evaluator!
  include(evaluator)
end
copy_into_tree(source_context) click to toggle source
# File lib/xspec/data_structures.rb, line 97
def copy_into_tree(source_context)
  target_context = make(
    source_context.name,
    source_context.evaluator
  )
  source_context.nested_units_of_work.each do |x|
    target_context.units_of_work << x.unit_of_work
  end
  self.children << target_context
  target_context
end
create_shared_context(&block) click to toggle source

A shared context is a floating context that isn't part of any context heirachy, so its units of work will not be visible to the root node. It can be brought into any point in the heirachy using `copy_into_tree` (aliased as `include_context` in the DSL), and this can be done multiple times, which allows definitions to be reused.

This is leaky abstraction, since only units of work are copied from shared contexts. Methods and child contexts are ignored.

# File lib/xspec/data_structures.rb, line 93
def create_shared_context(&block)
  make(nil, evaluator, &block)
end
execute(unit_of_work) click to toggle source

Executing a unit of work creates a new instance and hands it off to the `call` method, which is defined by whichever assertion context is being used. By creating a new instance everytime, no state is preserved between executions.

# File lib/xspec/data_structures.rb, line 65
def execute(unit_of_work)
  new.call(unit_of_work)
end
initialize!(name, evaluator) click to toggle source

A class cannot have an implicit initializer, but some variable inititialization is required so the `initialize!` method is called explicitly when ever a dynamic subclass is created.

# File lib/xspec/data_structures.rb, line 47
def initialize!(name, evaluator)
  @children          = []
  @units_of_work     = []
  @name              = name
  @evaluator = evaluator
end
make(name, evaluator, &block) click to toggle source

Each nested context creates a new class that inherits from the parent. Methods can be added to this class as per normal, and are correctly inherited by children. When it comes time to run tests, the scheduler will create a new instance of the context (a class) for each test, making the defined methods available and also ensuring that there is no state pollution between tests.

# File lib/xspec/data_structures.rb, line 36
def make(name, evaluator, &block)
  x = Class.new(self)
  x.initialize!(name, evaluator)
  x.class_eval(&block) if block
  x.apply_evaluator!
  x
end
nested_units_of_work(&block) click to toggle source
# File lib/xspec/data_structures.rb, line 112
def nested_units_of_work(&block)
  enum = Enumerator.new do |y|
    children.each do |child|
      child.nested_units_of_work do |x|
        y.yield x.nest_under(self)
      end
    end

    units_of_work.each do |x|
      y.yield NestedUnitOfWork.new([self], x)
    end
  end

  if block
    enum.each(&block)
  else
    enum
  end
end
root(evaluator) click to toggle source

The root context is nothing special, and behaves the same as all the others.

# File lib/xspec/data_structures.rb, line 71
def root(evaluator)
  make(nil, evaluator)
end
to_s() click to toggle source

Dynamically generated classes are hard to identify in object graphs, so it is helpful for debugging to set an explicit name.

# File lib/xspec/data_structures.rb, line 143
def to_s
  "Context:'#{name}'"
end

Public Instance Methods

memoized() click to toggle source
# File lib/xspec/data_structures.rb, line 148
def memoized
  @memoized ||= {}
end