Module: XSpec
- Defined in:
- lib/xspec.rb,
lib/xspec/dsl.rb,
lib/xspec/defaults.rb,
lib/xspec/notifiers.rb,
lib/xspec/evaluators.rb,
lib/xspec/schedulers.rb,
lib/xspec/data_structures.rb
Overview
XSpec data structures are very dumb. They:
-
Only contain iteration, property, and creation logic.
-
Do not store recursive references (“everything flows downhill”).
Defined Under Namespace
Modules: DSL, Evaluator, Notifier, Scheduler Classes: Context, ExecutedUnitOfWork, Failure, NestedUnitOfWork, UnitOfWork
Constant Summary collapse
- CodeException =
An exception is mostly handled the same way as a failure.
Class.new(Failure)
Class Method Summary collapse
- .add_defaults(options = {}) ⇒ Object
- .default_short_id(uow) ⇒ Object
-
.dsl(config = {}) ⇒ Object
The DSL is the core of XSpec.
Class Method Details
.add_defaults(options = {}) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/xspec/defaults.rb', line 25 def add_defaults( = {}) # A notifier makes it possible to observe the state of the system, be that # progress or details of failing tests. [:notifier] ||= XSpec::Notifier::DEFAULT # A unit of work will run as an instance method on the context it is # defined in, but in addition an assertion context will be added as well. # This is a module that is included as the final step in constructing a # context. Allows for different matchers and expectation frameworks to be # used. [:evaluator] ||= Evaluator::DEFAULT [:short_id] ||= XSpec.method(:default_short_id) # An scheduler is responsible for scheduling units of work and handing them # off to the assertion context. Any logic regarding threads, remote # execution or the like belongs in a scheduler. [:scheduler] ||= Scheduler::DEFAULT end |
.default_short_id(uow) ⇒ Object
13 14 15 16 17 18 19 20 21 22 |
# File 'lib/xspec/defaults.rb', line 13 def default_short_id(uow) length = 3 base = 32 digest = Digest::SHA1.hexdigest(uow.full_name).hex bottom = base ** (length-1) top = base ** length shifted = digest % (top - bottom) + bottom shifted.to_s(base) end |
.dsl(config = {}) ⇒ Object
The DSL is the core of XSpec. It dynamically generates a module that can be mixed into which ever context you choose (using ‘extend`), be that the top-level namespace or a specific class.
This enables different options to be specified per DSL, which is at the heart of XSpec’s modularity. It is easy to change every component to your liking.
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/xspec.rb', line 15 def dsl(config = {}) config = XSpec.add_defaults(config) Module.new do # Each DSL provides a standard set of methods provided by the [DSL # module](dsl.html). include DSL # In addition, each DSL has its own independent context, which is # described in detail in the # [`data_structures.rb`](data_structures.html). def __xspec_context evaluator = __xspec_config.fetch(:evaluator) @__xspec_context ||= XSpec::Context.root(evaluator) end # Some meta-magic is needed to enable the config from local scope above # to be available inside the module. define_method(:__xspec_config) { config } # `run!` is where the magic happens. Typically called at the end of a # file (or by `autorun!`), this method takes all the data that was # accumulated by the DSL methods above and runs it through the scheduler. # # It takes an optional block that can be used to override any options # set in the initial `XSpec.dsl` call. def run!(&overrides) overrides ||= -> x { x } config = overrides.(__xspec_config) scheduler = config.fetch(:scheduler) scheduler.run(__xspec_context, config) end # It is often convenient to trigger a run after all files have been # processed, which is what `autorun!` sets up for you. Requiring # `xspec/autorun` does this automatically for you. def autorun! at_exit do exit 1 unless run! end end end end |