Testing
Ductwork provides custom RSpec matchers and some helpers to simplify pipeline testing.
RSpec matchers
Section titled “RSpec matchers”have_triggered_pipeline
Section titled “have_triggered_pipeline”Use this matcher to verify that a single pipeline was triggered. It requires a block and takes one pipeline class as its argument.
expect do MyService.callend.to have_triggered_pipeline(MyPipeline)Specifying Execution Count
Section titled “Specifying Execution Count”You can assert that a pipeline was triggered a specific number of times:
expect do MyService.callend.to have_triggered_pipeline(MyPipeline).exactly(3).timeshave_triggered_pipelines
Section titled “have_triggered_pipelines”Use this matcher to verify that multiple pipelines were triggered. It takes multiple pipeline classes as arguments.
expect do MyService.callend.to have_triggered_pipelines(MyPipelineA, MyPipelineB, MyPipelineC)Note: This matcher does not support count expectations, as specifying counts for multiple pipelines would be ambiguous.
Creating steps
Section titled “Creating steps”Because of Reasons, Ductwork steps are built in a non-standard way. This means you need to use the following to instantiate steps:
let(:step) { FetchUserData.build_for_execution(pipeline_id, attrs) }The first argument is the pipeline ID to which the step belongs followed by any input arguments.
Creating pipelines
Section titled “Creating pipelines”To make creating pipeline objects easier you can use the pipeline_for helper which only takes a class name:
let(:pipeline) { pipeline_for(EnrichAllUsersDataPipeline) }Setting context
Section titled “Setting context”Likewise there is a helper to make setting global state easier:
before do set_pipeline_context(pipeline, user_id: 1)endFor convenience, you can use string or symbol keys to set context state.
Pipeline validation
Section titled “Pipeline validation”It is useful to know if your pipeline and step classes are valid before pushing to production. There is a top-level Ductwork.validate! method that will ensure your step classes have the correct methods and arity and that each pipeline is calling transitions correctly. It is recommended to call this method in a test:
RSpec.describe "Ductwork" do specify "valid pipelines and steps" do Ductwork.validate! endend