Class: XSpec::Context
- Inherits:
-
Object
- Object
- XSpec::Context
- Extended by:
- DSL
- Defined in:
- lib/xspec/data_structures.rb
Class Attribute Summary collapse
-
.children ⇒ Object
readonly
Returns the value of attribute children.
-
.evaluator ⇒ Object
readonly
Returns the value of attribute evaluator.
-
.name ⇒ Object
readonly
Returns the value of attribute name.
-
.units_of_work ⇒ Object
readonly
Returns the value of attribute units_of_work.
Class Method Summary collapse
-
.__xspec_context ⇒ Object
A context includes the same DSL methods as the root level module, which enables the recursive creation.
-
.add_child_context(name = nil, opts = {}, &block) ⇒ Object
Child contexts and units of work are typically added by the ‘describe` and `it` DSL methods respectively.
-
.add_memoized_method(name, &block) ⇒ Object
Values of memoized methods are remembered only for the duration of a single unit of work.
- .add_unit_of_work(name = nil, opts = {}, &block) ⇒ Object
-
.apply_evaluator! ⇒ Object
The assertion context should be applied after the user has had a chance to add their own methods.
- .copy_into_tree(source_context) ⇒ Object
-
.create_shared_context(&block) ⇒ Object
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.
-
.execute(unit_of_work) ⇒ Object
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.
-
.initialize!(name, evaluator) ⇒ Object
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.
-
.make(name, evaluator, &block) ⇒ Object
Each nested context creates a new class that inherits from the parent.
- .nested_units_of_work(&block) ⇒ Object
-
.root(evaluator) ⇒ Object
The root context is nothing special, and behaves the same as all the others.
-
.to_s ⇒ Object
Dynamically generated classes are hard to identify in object graphs, so it is helpful for debugging to set an explicit name.
Instance Method Summary collapse
Methods included from DSL
describe, it, it_behaves_like_a, let, shared_context
Class Attribute Details
.children ⇒ Object (readonly)
Returns the value of attribute children.
23 24 25 |
# File 'lib/xspec/data_structures.rb', line 23 def children @children end |
.evaluator ⇒ Object (readonly)
Returns the value of attribute evaluator.
23 24 25 |
# File 'lib/xspec/data_structures.rb', line 23 def evaluator @evaluator end |
.name ⇒ Object (readonly)
Returns the value of attribute name.
23 24 25 |
# File 'lib/xspec/data_structures.rb', line 23 def name @name end |
.units_of_work ⇒ Object (readonly)
Returns the value of attribute units_of_work.
23 24 25 |
# File 'lib/xspec/data_structures.rb', line 23 def units_of_work @units_of_work end |
Class Method Details
.__xspec_context ⇒ Object
A context includes the same DSL methods as the root level module, which enables the recursive creation.
27 |
# File 'lib/xspec/data_structures.rb', line 27 def __xspec_context; self; end |
.add_child_context(name = nil, opts = {}, &block) ⇒ Object
Child contexts and units of work are typically added by the ‘describe` and `it` DSL methods respectively.
77 78 79 |
# 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) ⇒ Object
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.
135 136 137 138 139 |
# 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) ⇒ Object
81 82 83 |
# 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! ⇒ Object
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.
57 58 59 |
# File 'lib/xspec/data_structures.rb', line 57 def apply_evaluator! include(evaluator) end |
.copy_into_tree(source_context) ⇒ Object
97 98 99 100 101 102 103 104 105 106 107 |
# 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) ⇒ Object
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 `it_behaves_like_a` 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.
93 94 95 |
# File 'lib/xspec/data_structures.rb', line 93 def create_shared_context(&block) make(nil, evaluator, &block) end |
.execute(unit_of_work) ⇒ Object
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.
65 66 67 |
# File 'lib/xspec/data_structures.rb', line 65 def execute(unit_of_work) new.call(unit_of_work) end |
.initialize!(name, evaluator) ⇒ Object
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.
47 48 49 50 51 52 |
# 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) ⇒ Object
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.
36 37 38 39 40 41 42 |
# 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) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# 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) ⇒ Object
The root context is nothing special, and behaves the same as all the others.
71 72 73 |
# File 'lib/xspec/data_structures.rb', line 71 def root(evaluator) make(nil, evaluator) end |
.to_s ⇒ Object
Dynamically generated classes are hard to identify in object graphs, so it is helpful for debugging to set an explicit name.
143 144 145 |
# File 'lib/xspec/data_structures.rb', line 143 def to_s "Context:'#{name}'" end |
Instance Method Details
#memoized ⇒ Object
148 149 150 |
# File 'lib/xspec/data_structures.rb', line 148 def memoized @memoized ||= {} end |