Back to results

Filtered result set

80 / 1836 matches

SkillHub ClubRun DevOpsTestingFull StackDevOps

n8n-workflow-testing-fundamentals

Provides structured testing methods for n8n workflows, including validation, execution testing, and error handling. Offers code examples for common testing scenarios and coordination patterns for multi-agent testing.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
260
Hot score
98
Updated
March 20, 2026
Overall rating
A7.7
Composite score
7.0
Best-practice grade
S96.0

Install command

npx @skill-hub/cli install proffesor-for-testing-agentic-qe-n8n-workflow-testing-fundamentals
n8nworkflow-testingautomationintegration-testingdevops

Repository

proffesor-for-testing/agentic-qe

Skill path: .claude/skills/n8n-workflow-testing-fundamentals

Provides structured testing methods for n8n workflows, including validation, execution testing, and error handling. Offers code examples for common testing scenarios and coordination patterns for multi-agent testing.

Open repository

Best for

Primary workflow: Run DevOps.

Technical facets: Testing, Full Stack, DevOps, Integration.

Target audience: Developers and QA engineers testing n8n workflow automations, particularly those using multi-agent testing approaches.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: proffesor-for-testing.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install n8n-workflow-testing-fundamentals into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/proffesor-for-testing/agentic-qe before adding n8n-workflow-testing-fundamentals to shared team environments
  • Use n8n-workflow-testing-fundamentals for testing workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: n8n-workflow-testing-fundamentals
description: "Comprehensive n8n workflow testing including execution lifecycle, node connection patterns, data flow validation, and error handling strategies. Use when testing n8n workflow automation applications."
category: n8n-testing
priority: high
tokenEstimate: 1200
agents: [n8n-workflow-executor, n8n-node-validator, n8n-trigger-test]
implementation_status: production
optimization_version: 1.0
last_optimized: 2025-12-15
dependencies: []
quick_reference_card: true
tags: [n8n, workflow, automation, testing, data-flow, nodes, triggers]
---

# n8n Workflow Testing Fundamentals

<default_to_action>
When testing n8n workflows:
1. VALIDATE workflow structure before execution
2. TEST with realistic test data
3. VERIFY node-to-node data flow
4. CHECK error handling paths
5. MEASURE execution performance

**Quick n8n Testing Checklist:**
- All nodes properly connected (no orphans)
- Trigger node correctly configured
- Data mappings between nodes valid
- Error workflows defined
- Credentials properly referenced

**Critical Success Factors:**
- Test each execution path separately
- Validate data transformations at each node
- Check retry and error handling behavior
- Verify integrations with external services
</default_to_action>

## Quick Reference Card

### When to Use
- Testing new n8n workflows
- Validating workflow changes
- Debugging failed executions
- Performance optimization
- Pre-deployment validation

### n8n Workflow Components

| Component | Purpose | Testing Focus |
|-----------|---------|---------------|
| **Trigger** | Starts workflow | Reliable activation, payload handling |
| **Action Nodes** | Process data | Configuration, data mapping |
| **Logic Nodes** | Control flow | Conditional routing, branches |
| **Integration Nodes** | External APIs | Auth, rate limits, errors |
| **Error Workflow** | Handle failures | Recovery, notifications |

### Workflow Execution States

| State | Meaning | Test Action |
|-------|---------|-------------|
| `running` | Currently executing | Monitor progress |
| `success` | Completed successfully | Validate outputs |
| `failed` | Execution failed | Analyze error |
| `waiting` | Waiting for trigger | Test trigger mechanism |

---

## Workflow Structure Validation

```typescript
// Validate workflow structure before execution
async function validateWorkflowStructure(workflowId: string) {
  const workflow = await getWorkflow(workflowId);

  // Check for trigger node
  const triggerNode = workflow.nodes.find(n =>
    n.type.includes('trigger') || n.type.includes('webhook')
  );
  if (!triggerNode) {
    throw new Error('Workflow must have a trigger node');
  }

  // Check for orphan nodes (no connections)
  const connectedNodes = new Set();
  for (const [source, targets] of Object.entries(workflow.connections)) {
    connectedNodes.add(source);
    for (const outputs of Object.values(targets)) {
      for (const connections of outputs) {
        for (const conn of connections) {
          connectedNodes.add(conn.node);
        }
      }
    }
  }

  const orphans = workflow.nodes.filter(n => !connectedNodes.has(n.name));
  if (orphans.length > 0) {
    console.warn('Orphan nodes detected:', orphans.map(n => n.name));
  }

  // Validate credentials
  for (const node of workflow.nodes) {
    if (node.credentials) {
      for (const [type, ref] of Object.entries(node.credentials)) {
        if (!await credentialExists(ref.id)) {
          throw new Error(`Missing credential: ${type} for node ${node.name}`);
        }
      }
    }
  }

  return { valid: true, orphans, triggerNode };
}
```

---

## Execution Testing

```typescript
// Test workflow execution with various inputs
async function testWorkflowExecution(workflowId: string, testCases: TestCase[]) {
  const results: TestResult[] = [];

  for (const testCase of testCases) {
    const startTime = Date.now();

    // Execute workflow
    const execution = await executeWorkflow(workflowId, testCase.input);

    // Wait for completion
    const result = await waitForCompletion(execution.id, testCase.timeout || 30000);

    // Validate output
    const outputValid = validateOutput(result.data, testCase.expected);

    results.push({
      testCase: testCase.name,
      success: result.status === 'success' && outputValid,
      duration: Date.now() - startTime,
      actualOutput: result.data,
      expectedOutput: testCase.expected
    });
  }

  return results;
}

// Example test cases
const testCases = [
  {
    name: 'Valid customer data',
    input: { name: 'John Doe', email: '[email protected]' },
    expected: { processed: true, customerId: /^cust_/ },
    timeout: 10000
  },
  {
    name: 'Missing email',
    input: { name: 'Jane Doe' },
    expected: { error: 'Email required' },
    timeout: 5000
  },
  {
    name: 'Invalid email format',
    input: { name: 'Bob', email: 'not-an-email' },
    expected: { error: 'Invalid email' },
    timeout: 5000
  }
];
```

---

## Data Flow Validation

```typescript
// Trace data through workflow nodes
async function validateDataFlow(executionId: string) {
  const execution = await getExecution(executionId);
  const nodeResults = execution.data.resultData.runData;

  const dataFlow: DataFlowStep[] = [];

  for (const [nodeName, runs] of Object.entries(nodeResults)) {
    for (const run of runs) {
      dataFlow.push({
        node: nodeName,
        input: run.data?.main?.[0]?.[0]?.json || {},
        output: run.data?.main?.[0]?.[0]?.json || {},
        executionTime: run.executionTime,
        status: run.executionStatus
      });
    }
  }

  // Validate data transformations
  for (let i = 1; i < dataFlow.length; i++) {
    const prev = dataFlow[i - 1];
    const curr = dataFlow[i];

    // Check if expected data passed through
    validateDataMapping(prev.output, curr.input);
  }

  return dataFlow;
}

// Validate data mapping between nodes
function validateDataMapping(sourceOutput: any, targetInput: any) {
  // Check all required fields are present
  const missingFields: string[] = [];

  for (const [key, value] of Object.entries(targetInput)) {
    if (value === undefined && sourceOutput[key] === undefined) {
      missingFields.push(key);
    }
  }

  if (missingFields.length > 0) {
    console.warn('Missing fields in data mapping:', missingFields);
  }

  return missingFields.length === 0;
}
```

---

## Error Handling Testing

```typescript
// Test error handling paths
async function testErrorHandling(workflowId: string) {
  const errorScenarios = [
    {
      name: 'API timeout',
      inject: { delay: 35000 }, // Trigger timeout
      expectedError: 'timeout'
    },
    {
      name: 'Invalid data',
      inject: { invalidField: true },
      expectedError: 'validation'
    },
    {
      name: 'Missing credentials',
      inject: { removeCredentials: true },
      expectedError: 'authentication'
    }
  ];

  const results: ErrorTestResult[] = [];

  for (const scenario of errorScenarios) {
    // Execute with error injection
    const execution = await executeWithErrorInjection(workflowId, scenario.inject);

    // Check error was caught
    const result = await waitForCompletion(execution.id);

    // Validate error handling
    results.push({
      scenario: scenario.name,
      errorCaught: result.status === 'failed',
      errorType: result.data?.resultData?.error?.type,
      expectedError: scenario.expectedError,
      errorWorkflowTriggered: await checkErrorWorkflowTriggered(execution.id),
      alertSent: await checkAlertSent(execution.id)
    });
  }

  return results;
}

// Verify error workflow was triggered
async function checkErrorWorkflowTriggered(executionId: string): Promise<boolean> {
  const errorExecutions = await getExecutions({
    filter: {
      metadata: { errorTriggeredBy: executionId }
    }
  });

  return errorExecutions.length > 0;
}
```

---

## Node Connection Patterns

### Linear Flow
```
Trigger → Process → Transform → Output
```
**Testing:** Execute once, validate each node output

### Branching Flow
```
Trigger → IF → [Branch A] → Merge → Output
              → [Branch B] →
```
**Testing:** Test both branches separately, verify merge behavior

### Parallel Flow
```
Trigger → Split → [Process A] → Merge → Output
                → [Process B] →
```
**Testing:** Validate parallel execution, check merge timing

### Loop Flow
```
Trigger → SplitInBatches → Process → [Loop back until done] → Output
```
**Testing:** Test with varying batch sizes, verify all items processed

---

## Common Testing Patterns

### Test Data Generation

```typescript
// Generate test data for common n8n patterns
const testDataGenerators = {
  webhook: () => ({
    body: { event: 'test', timestamp: new Date().toISOString() },
    headers: { 'Content-Type': 'application/json' },
    query: { source: 'test' }
  }),

  slack: () => ({
    type: 'message',
    channel: 'C123456',
    user: 'U789012',
    text: 'Test message'
  }),

  github: () => ({
    action: 'opened',
    issue: {
      number: 1,
      title: 'Test Issue',
      body: 'Test body'
    },
    repository: {
      full_name: 'test/repo'
    }
  }),

  stripe: () => ({
    type: 'payment_intent.succeeded',
    data: {
      object: {
        id: 'pi_test123',
        amount: 1000,
        currency: 'usd'
      }
    }
  })
};
```

### Execution Assertions

```typescript
// Common assertions for workflow execution
const workflowAssertions = {
  // Assert workflow completed
  assertCompleted: (execution) => {
    expect(execution.finished).toBe(true);
    expect(execution.status).toBe('success');
  },

  // Assert specific node executed
  assertNodeExecuted: (execution, nodeName) => {
    const nodeData = execution.data.resultData.runData[nodeName];
    expect(nodeData).toBeDefined();
    expect(nodeData[0].executionStatus).toBe('success');
  },

  // Assert data transformation
  assertDataTransformed: (execution, nodeName, expectedData) => {
    const nodeOutput = execution.data.resultData.runData[nodeName][0].data.main[0][0].json;
    expect(nodeOutput).toMatchObject(expectedData);
  },

  // Assert execution time
  assertExecutionTime: (execution, maxMs) => {
    const duration = new Date(execution.stoppedAt) - new Date(execution.startedAt);
    expect(duration).toBeLessThan(maxMs);
  }
};
```

---

## Agent Coordination Hints

### Memory Namespace
```
aqe/n8n/
├── workflows/*          - Cached workflow definitions
├── test-results/*       - Test execution results
├── validations/*        - Validation reports
├── patterns/*           - Discovered testing patterns
└── executions/*         - Execution tracking
```

### Fleet Coordination
```typescript
// Comprehensive n8n testing with fleet
const n8nFleet = await FleetManager.coordinate({
  strategy: 'n8n-testing',
  agents: [
    'n8n-workflow-executor',  // Execute and validate
    'n8n-node-validator',     // Validate configurations
    'n8n-trigger-test',       // Test triggers
    'n8n-expression-validator', // Validate expressions
    'n8n-integration-test'    // Test integrations
  ],
  topology: 'parallel'
});
```

---

## Related Skills
- [n8n-expression-testing](../n8n-expression-testing/) - Expression validation
- [n8n-trigger-testing-strategies](../n8n-trigger-testing-strategies/) - Trigger testing
- [n8n-integration-testing-patterns](../n8n-integration-testing-patterns/) - Integration testing
- [n8n-security-testing](../n8n-security-testing/) - Security validation

---

## Remember

**n8n workflows are JSON-based execution flows** that connect 400+ services. Testing requires validating:
- Workflow structure (nodes, connections)
- Trigger reliability (webhooks, schedules)
- Data flow (transformations between nodes)
- Error handling (retry, fallback, notifications)
- Performance (execution time, resource usage)

**With Agents:** Use n8n-workflow-executor for execution testing, n8n-node-validator for configuration validation, and coordinate multiple agents for comprehensive workflow testing.
n8n-workflow-testing-fundamentals | SkillHub