Module: BoltSpec

Defined in:
lib/bolt_spec/run.rb,
lib/bolt_spec/plans.rb,
lib/bolt_spec/plans/mock_executor.rb

Overview

These helpers are intended to be used for plan unit testing without calling out to target nodes. It accomplishes this by replacing bolt’s executor with a mock executor. The mock executor allows calls to run_* functions to be stubbed out for testing. By default this executor will fail on any run_* call but stubs can be set up with allow_* and expect_* functions.

Stub matching

Stubs match invocations of run_* functions by default matching any call but with_targets and with_params helpers can further restrict the stub to match more exact invocations. It’s possible a call to run_* could match multiple stubs. In this case the mock executor will first check for stubs specifically matching the task being run after which it will use the last stub that matched

allow vs expect

Stubs have two general modes bases on whether the test is making assertions on whether function was called. Allow stubs allow the run_* invocation to be called any number of times while expect stubs will fail if no run_* invocation matches them. The be_called_times(n) stub method can be used to ensure an allow stub is not called more than n times or that an expect stub is called exactly n times.

Configuration

By default the plan helpers use the modulepath set up for rspec-puppet and
an otherwise empty bolt config and inventory. To create your own values for
these override the modulepath, config, or inventory methods.

TODO:
- allow stubbing for commands, scripts and file uploads
- Allow description based stub matching
- Better testing of plan errors
- Better error collection around call counts. Show what stubs exists and more than a single failure
- Allow stubbing with a block(at the double level? As a matched stub?)
- package code so that it can be used for testing modules outside of this repo
- set subject from describe and provide matchers similar to rspec puppets function tests

MAYBE TODO?:
- allow stubbing for subplans
- validate call expectations at the end of the example instead of in run_plan
- resultset matchers to help testing canary like plans?
- inventory matchers to help testing plans that change inventory

Example:

describe "my_plan" do
  it 'should return' do
    allow_task('my_task').always_return({'result_key' => 10})
    expect(run_plan('my_plan', { 'param1' => 10 })).to be
  end

  it 'should call task with param1' do
    expect_task('my_task').with_params('param1' => 10).always_return({'result_key' => 10})
    expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
  end

  it 'should call task with param1 once' do
    expect_task('my_task').with_params('param1' => 10).always_return({'result_key' => 10}).be_called_times(1)
    expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
  end

  it 'should not_call task with 100' do
    allow_task('my_task').always_return({'result_key' => 10})
    # Any call with param1 => 100 will match this since it's added second
    expect_task('my_task').with_params('param1' => 100).not_be_called
    expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
  end

  it 'should be called on both node1 and node2' do
    expect_task('my_task').with_targets(['node1', 'node2']).always_return({'result_key' => 10})
    expect(run_plan('my_plan', { 'param1' => 10 })).to eq(10)
  end

  it 'should average results from targets' do
    expect_task('my_task').return_for_targets({
      'node1' => {'result_key' => 20},
      'node2' => {'result_key' => 6} })
    expect(run_plan('my_plan', { 'param1' => 10 })).to eq(13)
  end
end

Defined Under Namespace

Modules: Plans, Run