Module: Roby::Test::ExpectExecution

Included in:
MinitestHelpers, TeardownPlans
Defined in:
lib/roby/test/expect_execution.rb

Overview

Test related to execution in a Roby context

This is the public interface of Roby’s test swiss-army knife #expect_execution

The block given to #expect_execution will be executed in Roby’s event propagation context, and then some expectations can be matched against the result using the .to call:

expect_execution { ...code to be executed... }
   .to { ... expectations ... }

See the ‘Expectations’ section of ExecutionExpectations for an exhaustive list of existing expectations. Additional setup regarding the processing loop is documented in the Setup section of the same page, and can be used like this:

expect_execution { ...code to be executed... }
   .timeout(10)
   .scheduler(true)
   .to { ... expectations ... }

The execution expectation object is actually executed when one of the to_run or to { } methods is called. The former runs the block without any expectation (and therefore runs it only once, or until all async work is finished). The latter defines expectations and verifies them.

Note that the heavy-lifting is done in ExecutionExpectations. This is really only the sugar-coating above the test harness itself.

Examples:

emit an event and validate that it is emitted

plan.add(task = MyTask.new)
expect_execution { task.start! }
   .to { emit task.start_event }

Defined Under Namespace

Classes: Context, InvalidContext

Constant Summary collapse

SETUP_METHODS =
%i[
    timeout
    wait_until_timeout
    join_all_waiting_work
    scheduler
    garbage_collect
    validate_unexpected_errors
    display_exceptions
    poll
].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#expect_execution_default_timeoutObject

Returns the value of attribute expect_execution_default_timeout.



94
95
96
# File 'lib/roby/test/expect_execution.rb', line 94

def expect_execution_default_timeout
  @expect_execution_default_timeout
end

Instance Method Details

#add_expectations(&block) ⇒ Object

Add an expectation from within an execute { } or expect_execution { } block

Raises:



163
164
165
166
167
168
169
# File 'lib/roby/test/expect_execution.rb', line 163

def add_expectations(&block)
    unless @current_expect_execution
        raise InvalidContext, "#add_expectations not called within an expect_execution context"
    end

    @current_expect_execution.expectations.parse(ret: false, &block)
end

#execute(plan: self.plan, garbage_collect: false) ⇒ Object

Execute a block within the event propagation context



136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/roby/test/expect_execution.rb', line 136

def execute(plan: self.plan, garbage_collect: false)
    unless plan.respond_to?(:execution_engine)
        # not an executable plan, just yield
        return yield
    end

    result = nil
    expect_execution(plan: plan) { result = yield }.garbage_collect(garbage_collect).to_run
    result
rescue Minitest::Assertion => e
    raise e, e.message, caller(2)
end

#execute_one_cycle(plan: self.plan, scheduler: false, garbage_collect: false) ⇒ Object

Run exactly once cycle



150
151
152
153
154
155
156
# File 'lib/roby/test/expect_execution.rb', line 150

def execute_one_cycle(plan: self.plan, scheduler: false, garbage_collect: false)
    expect_execution(plan: plan)
        .join_all_waiting_work(false)
        .scheduler(scheduler)
        .garbage_collect(garbage_collect)
        .to_run
end

#expect_execution(plan: self.plan, &block) ⇒ Object

Declare expectations about the execution of a code block

See the documentation of Roby::Test::ExpectExecution for more details

Raises:

  • (InvalidContext)

    if expect_execution is used from within an expect_execution context, or within propagation context



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/roby/test/expect_execution.rb', line 102

def expect_execution(plan: self.plan, &block)
    if plan.execution_engine.in_propagation_context?
        raise InvalidContext, "cannot recursively call #expect_execution"
    end

    expectations = ExecutionExpectations.new(self, plan)
    context = Context.new(self, expectations, block)
    if @expect_execution_default_timeout
        context.timeout(@expect_execution_default_timeout)
    end
    context
end

#reset_current_expect_executionObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reset the current expect_execution block. This is used to check for recursive calls to #expect_execution



131
132
133
# File 'lib/roby/test/expect_execution.rb', line 131

def reset_current_expect_execution
    @current_expect_execution = nil
end

#setup_current_expect_execution(context) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set the current expect_execution context. This is used to check for recursive calls to #expect_execution



119
120
121
122
123
124
125
# File 'lib/roby/test/expect_execution.rb', line 119

def setup_current_expect_execution(context)
    if @current_expect_execution
        raise InvalidContext, "cannot perform an expect_execution test within another one"
    end

    @current_expect_execution = context
end