Class: Buildr::Checks::Expectation

Inherits:
Object
  • Object
show all
Defined in:
lib/buildr/core/checks.rb

Overview

An expectation has subject, description and block. The expectation is validated by running the block, and can access the subject from the method #it. The description is used for reporting.

The expectation is run by calling #run_against. You can share expectations by running them against different projects (or any other context for that matter).

If the subject is missing, it is set to the argument of #run_against, typically the project itself. If the description is missing, it is set from the project. If the block is missing, the default behavior prints “Pending” followed by the description. You can use this to write place holders and fill them later.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, &block) ⇒ Expectation

:call-seq:

initialize(subject, description?) { .... }
initialize(description?) { .... }

First argument is subject (returned from it method), second argument is description. If you omit the description, it will be set from the subject. If you omit the subject, it will be set from the object passed to run_against.

Raises:

  • (ArgumentError)


89
90
91
92
93
94
# File 'lib/buildr/core/checks.rb', line 89

def initialize(*args, &block)
  @description = args.pop if String === args.last
  @subject = args.shift
  raise ArgumentError, "Expecting subject followed by description, and either one is optional. Not quite sure what to do with this list of arguments." unless args.empty?
  @block = block || lambda { info "Pending: #{description}" }
end

Instance Attribute Details

#blockObject (readonly)

Returns the value of attribute block.



80
81
82
# File 'lib/buildr/core/checks.rb', line 80

def block
  @block
end

#descriptionObject (readonly)

Returns the value of attribute description.



80
81
82
# File 'lib/buildr/core/checks.rb', line 80

def description
  @description
end

#subjectObject (readonly)

Returns the value of attribute subject.



80
81
82
# File 'lib/buildr/core/checks.rb', line 80

def subject
  @subject
end

Instance Method Details

#run_against(context) ⇒ Object

:call-seq:

run_against(context)

Runs this expectation against the context object. The context object is different from the subject, but used as the subject if no subject specified (i.e. returned from the it method).

This method creates a new context object modeled after the context argument, but a separate object used strictly for running this expectation, and used only once. The context object will pass methods to the context argument, so you can call any method, e.g. package(:jar).

It also adds all matchers defined in Buildr and RSpec, and two additional methods:

  • it() – Returns the subject.

  • description() – Returns the description.



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/buildr/core/checks.rb', line 109

def run_against(context)
  subject = @subject || context
  description = @description ? "#{subject} #{@description}" : subject.to_s
  # Define anonymous class and load it with:
  # - All instance methods defined in context, so we can pass method calls to the context.
  # - it() method to return subject, description() method to return description.
  # - All matchers defined by Buildr and RSpec.
  klass = Class.new
  klass.instance_eval do
    context.class.instance_methods.each do |method|
      define_method(method) { |*args| context.send(method, *args) } unless instance_methods.include?(method)
    end
    define_method(:it) { subject }
    define_method(:description) { description }
    include Spec::Matchers
    include Matchers
  end

  # Run the expectation. We only print the expectation name when tracing (to know they all ran),
  # or when we get a failure.
  begin
    trace description
    klass.new.instance_eval &@block
  rescue Exception=>error
    raise error.exception("#{description}\n#{error}").tap { |wrapped| wrapped.set_backtrace(error.backtrace) }
  end
end