workflow-tester
Find the payloads that break your n8n workflow before someone sends them. When a webhook arrives with a field set to null or an optional object missing, n8n turns the broken expression into undefined and shows no error. workflow-tester runs your workflow's expressions against those payloads and tells you which ones break and where. It runs offline, with no n8n instance.

Installation
Requires Node.js 24 or newer.
Run it without installing:
npx workflow-tester --help
Add it to a project:
npm install --save-dev workflow-tester
Build from source:
git clone https://github.com/LudwigGerdes/workflow-tester.git
cd workflow-tester
pnpm install && pnpm build
Getting started
Set up a project:
npx workflow-tester init
This creates:
.workflow-tester/
├── README.md
└── tests/
└── example.test.yaml
Download a sample sign-up workflow and a test file with three cases, then run them:
curl -L --create-dirs -o workflows/signup.json https://raw.githubusercontent.com/LudwigGerdes/workflow-tester/main/docs/demo/signup.json
curl -L -o .workflow-tester/tests/signup.test.yaml https://raw.githubusercontent.com/LudwigGerdes/workflow-tester/main/docs/demo/signup.test.yaml
npx workflow-tester run
Expected output:
workflows/signup.json
✗ no profile object, flat name — the ?? gotcha 1 expectation(s) fail
✗ node.Normalize.output[0].json.name: expected "Bob", got undefined
! "profile" is not produced here at Normalize → assignments.assignments[1].value
! "plan" is not produced here at Normalize → assignments.assignments[2].value
! no email at all every expectation held
! "email" is not produced here at Normalize → assignments.assignments[0].value
! "profile" is not produced here at Normalize → assignments.assignments[1].value
! "plan" is not produced here at Normalize → assignments.assignments[2].value
! "email" is not produced here at Normalize → assignments.assignments[3].value
✓ pro user with nested profile
1 passed, 1 failed, 1 warned in 354ms
The first case fails because the workflow reads $json.body.profile.first_name when there is no profile.
Usage
Write a test by hand, in .workflow-tester/tests/:
workflow: ../../workflows/signup.json
cases:
- id: flat-name
when:
trigger: webhook
payload:
email: bob@example.com
name: Bob
then:
node.Normalize.output[0].json.name: Bob
Run every test:
workflow-tester run
Generate tests from the payloads GitHub or Stripe can send:
workflow-tester contracts add workflows/issue-triage.json --vendor github --events issues-opened
workflow-tester gen
workflow-tester run --only generated
Turn a run you already made in n8n into a test:
workflow-tester capture workflows/invoice.json --execution execution.json
Report in a format your CI understands:
workflow-tester run --format junit