mcpField
Q
qe-n8n-workflow-testing-fundamentals

qe-n8n-workflow-testing-fundamentals

github.com/proffesor-for-testingテスト・品質51987 回インストール今日更新
リポジトリ

qe-n8n-workflow-testing-fundamentals について

n8n ワークフローのテスト実践ガイドです。実行前の構造確認、テストデータ、ノード間のデータフロー、エラー処理、性能測定を扱い、開発やデバッグ、デプロイ前の検証に役立ちます。

主な機能

  1. 01実行前のワークフロー構造確認
  2. 02テストデータによる実行検証
  3. 03ノード間のデータフロー確認
  4. 04エラーとリトライ経路のテスト
  5. 05実行性能の測定

活用シーン

  1. 01新しい n8n ワークフローの検証
  2. 02失敗したワークフロー実行のデバッグ
  3. 03デプロイ前の変更確認
  4. 04ワークフロー実行性能の最適化

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/proffesor-for-testing/agentic-qe --skill qe-n8n-workflow-testing-fundamentals

インストール後、Claude Code で/qe-n8n-workflow-testing-fundamentalsを入力して読み込まれたか確認します。

詳細

n8n ワークフローテストの基本

<default_to_action> n8n ワークフローをテストする際は、次の手順に従います。

  1. 実行前にワークフローの構造を検証します
  2. 現実的なテストデータでテストします
  3. ノード間のデータフローを確認します
  4. エラー処理の経路を確認します
  5. 実行パフォーマンスを測定します

n8n のクイックテストチェックリスト:

  • すべてのノードが正しく接続されている(孤立したノードがない)
  • トリガーノードが正しく設定されている
  • ノード間のデータマッピングが有効である
  • エラーワークフローが定義されている
  • 認証情報が正しく参照されている

成功のための重要な要素:

  • 各実行経路を個別にテストする
  • 各ノードでデータ変換を検証する
  • 再試行とエラー処理の動作を確認する
  • 外部サービスとの連携を確認する </default_to_action>

クイックリファレンスカード

使用するタイミング
  • 新しい n8n ワークフローのテスト
  • ワークフローの変更の検証
  • 失敗した実行のデバッグ
  • パフォーマンスの最適化
  • デプロイ前の検証
n8n ワークフローのコンポーネント
コンポーネント目的テストの重点
トリガーワークフローを開始します確実な起動、ペイロードの処理
アクションノードデータを処理します設定、データマッピング
ロジックノードフローを制御します条件付きルーティング、分岐
インテグレーションノード外部 API と連携します認証、レート制限、エラー
エラーワークフローエラーを処理します復旧、通知
ワークフローの実行状態
状態意味テストアクション
running実行中です進行状況を監視します
success正常に完了しました出力を検証します
failed実行に失敗しましたエラーを分析します
waitingトリガーを待機していますトリガーの仕組みをテストします

ワークフロー構造の検証

// 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 };
}

実行テスト

// 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
  }
];

データフローの検証

// 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;
}

エラー処理のテスト

// 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;
}

ノード接続のパターン

線形フロー
Trigger → Process → Transform → Output

テスト: 1 回実行し、各ノードの出力を検証します

分岐フロー
Trigger → IF → [Branch A] → Merge → Output
              → [Branch B] →

テスト: 両方の分岐を個別にテストし、マージの動作を確認します

並列フロー
Trigger → Split → [Process A] → Merge → Output
                → [Process B] →

テスト: 並列実行を検証し、マージのタイミングを確認します

ループフロー
Trigger → SplitInBatches → Process → [Loop back until done] → Output

テスト: バッチサイズを変えてテストし、すべての項目が処理されることを確認します


よくあるテストパターン

テストデータの生成
// 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'
      }
    }
  })
};
実行時のアサーション
// 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);
  }
};

エージェント連携のヒント

メモリの名前空間
aqe/n8n/
├── workflows/*          - Cached workflow definitions
├── test-results/*       - Test execution results
├── validations/*        - Validation reports
├── patterns/*           - Discovered testing patterns
└── executions/*         - Execution tracking
フリート連携
// 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'
});

関連スキル


お忘れなく

n8n ワークフローは、400 以上のサービスを連携する JSON ベースの実行フローです。 テストでは、次の項目を検証する必要があります。

  • ワークフローの構造(ノード、接続)
  • トリガーの信頼性(Webhook、スケジュール)
  • データフロー(ノード間の変換)
  • エラー処理(再試行、フォールバック、通知)
  • パフォーマンス(実行時間、リソース使用量)

エージェントを使用する場合: 実行テストには n8n-workflow-executor を、設定の検証には n8n-node-validator を使用し、包括的なワークフローテストのために複数のエージェントを連携させます。

コメント