Communityn8ngithub.com

ashtonfeliciano/n8n-evaluations-runner

建立並執行無 API 費用的邏輯測試套件,用於 n8n 工作流程。在為過濾邏輯、評分函式、驗證器、關鍵字清單、履歷對照表或任何純 JS 程式碼節點邏輯添加測試覆蓋率時使用。透過 Telegram 輸出分組的通過/失敗/待處理報告。在邏輯變更前後均執行,以在不消耗 API 額度的情況下捕捉回歸問題。

n8n-evaluations-runner 是什麼?

n8n Evaluations Runner 是一個專為 n8n 平台設計的輕量級、零 API 成本的邏輯測試工具。它允許開發者建立純邏輯測試套件,針對 Code 節點中的純 JavaScript 函式進行驗證,涵蓋過濾邏輯、關鍵字比對、驗證器等場景,且不耗費任何 API 額度。該工具透過手動觸發的工作流程執行,並將測試結果(通過/失敗/待處理)格式化後傳送至 Telegram 通知,支援自動化回歸測試。其核心是複製生產程式碼至測試節點,透過 `assert()` 函式進行斷言,並以套件為單位產生結構化報告。這個技能對於希望在不影響生產環境或消耗付費 API 呼叫的情況下,安全地重構或擴展 n8n 工作流程邏輯的開發者來說尤為實用,可作為預部署的防護網,將過往錯誤轉換為可重現的測試案例。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ashtonfeliciano/claude-skills-pack/tree/HEAD/skills/n8n-evaluations-runner

Installed? Explore more n8n skills: ashtonfeliciano/n8n-workflow-engineer, hubgunter4-ops/configurador-de-nodos-n8n, hubgunter4-ops/experto-en-n8n-mcp · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

n8n Evaluations Runner

何時觸發

  • 新增或修改過濾邏輯、關鍵字清單、驗證器或履歷對照表
  • 重構 Code 節點的純函式邏輯
  • 合併工作流程變更前 — 作為回歸防護
  • 生產事故發生後 — 將失敗案例編寫為測試
  • 「如何對 n8n 程式碼進行單元測試?」/「如何在不花費 API 額度的情況下進行測試?」

這是什麼(以及不是什麼)

這是這不是
一個僅包含邏輯且使用模擬輸入的 n8n 工作流程針對即時 API 的整合測試
無外部呼叫(除最終報告傳送外)— 約 3 秒內執行完畢效能測試
透過 Telegram 推送的通過/失敗/待處理計數端到端流程手動冒煙測試的替代方案
Code 節點中純 JS 的回歸防護網對 HTTP / Gmail / Telegram 節點行為的覆蓋

成本: 無 API 額度。僅使用記憶體中的模擬輸入。Telegram 報告是唯一的外部呼叫。

架構

[手動觸發] → [執行所有測試 (Code 節點)] → [格式化報告 (Code 節點)] → [傳送報告 (Telegram)]

每個邏輯表面一個工作流程。可按需重新執行。

標準測試執行器 Code 節點

const results = [];

function assert(suite, testName, condition, detail) {
  results.push({ suite, test: testName, pass: condition, detail: detail || '' });
}

// ============================================================
// 套件 1 — <名稱>
// ============================================================

// 在此處完全複製生產函式(不要匯入 — Code 節點不共享作用域)
function passesJs10Filter(job) {
  // ... 與生產節點相同的程式碼 ...
}

// 測試
assert('js-10', '拒絕需要安全許可的工作',
  !passesJs10Filter({
    title: 'Technical Writer',
    description: 'Clearance required.',
    location: 'remote'
  }),
  '必須觸發拒絕有安全許可要求的情況');

assert('js-10', '有效的遠端技術作家通過',
  passesJs10Filter({
    title: 'Technical Writer',
    description: 'Write API documentation for cloud platform.',
    location: 'remote'
  }),
  '有效的遠端技術作家應通過所有過濾器');

// 對於尚未實現的功能:
results.push({
  suite: 'js-10',
  test: '30 天期限篩選 (待處理 — 待辦事項)',
  pass: null,
  detail: '功能尚未實現。新增 postedAt 日期檢查,然後重新執行。'
});

// ============================================================
// 總結
// ============================================================

const passed  = results.filter(r => r.pass === true);
const failed  = results.filter(r => r.pass === false);
const pending = results.filter(r => r.pass === null);

return [{ json: {
  summary: { total: results.length, passed: passed.length, failed: failed.length, pending: pending.length },
  results, failed, pending
}}];

報告格式化工具

const { summary, results } = $input.first().json;

const passIcon = '✅';
const failIcon = '❌';
const pendIcon = '⏳';
const topEmoji = summary.failed === 0 ? '🟢' : (summary.failed <= 3 ? '🟡' : '🔴');

const lines = [
  `<b>${topEmoji} <NAME> — 邏輯評估</b>`,
  `${passIcon} ${summary.passed} 通過  ${failIcon} ${summary.failed} 失敗  ${pendIcon} ${summary.pending} 待處理`,
  ''
];

const suites = {};
for (const r of results) (suites[r.suite] = suites[r.suite] || []).push(r);

for (const [suite, tests] of Object.entries(suites)) {
  const suitePass = tests.every(t => t.pass !== false);
  lines.push(`<b>${suitePass ? passIcon : failIcon} ${suite}</b>`);
  for (const t of tests) {
    const icon = t.pass === true ? passIcon : (t.pass === false ? failIcon : pendIcon);
    lines.push(`  ${icon} ${t.test}`);
    if (t.pass !== true) lines.push(`    <i>→ ${(t.detail || '').substring(0, 140)}</i>`);
  }
  lines.push('');
}

const now = new Date().toLocaleString('en-US', {
  timeZone: 'UTC', dateStyle: 'short', timeStyle: 'short'
});
lines.push(`<i>執行時間:${now} UTC</i>`);

return [{ json: { message: lines.join('\n') } }];

Telegram 傳送節點(環境變數模式,無需 n8n 憑證)

{
  "method": "POST",
  "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
  "sendBody": true,
  "specifyBody": "keypair",
  "bodyParameters": {
    "parameters": [
      { "name": "chat_id", "value": "={{ $env.TELEGRAM_CHAT_ID }}" },
      { "name": "text", "value": "={{ $json.message }}" },
      { "name": "parse_mode", "value": "HTML" }
    ]
  }
}

測試優先順序

  1. 拒絕路徑覆蓋 — 記錄可能被過濾掉的每一種原因
  2. 邊界條件 — 臨界值、略低於臨界值、略高於臨界值
  3. 無效輸入的回退 — undefined、null、0、'None'、錯誤類型 → 預設值
  4. 已知正常的真實資料 — 至少一個來自過去確認可正常執行的範例
  5. 已知錯誤的真實資料 — 至少一個過去曾導致事故的範例
  6. 子字串與精確比對 — 例如 'HR Dept' 與 'Human Resources Department'
  7. 待處理功能 — 寫為 pass: null,使其在報告中顯示為待辦事項

測試命名慣例

<套件>: <人類可讀的斷言>,並在詳細資訊欄位中命名底層規則或過去錯誤的參考:

assert('js-22', '已拒絕 Human Resources Department',
  !isValidContact('Human Resources Department'),
  'BAD_CONTAINS_CONTACT 子字串比對必須捕捉此情況(Session 5 錯誤修復)');

「將過去錯誤轉換為測試」規則

在你的 Lessons Learned Library 中,每條提及特定輸入 → 錯誤行為的條目,都是一個等待被編寫的測試。

來自真實課程的範例:

"Aggregate Sector Quotes 正在計算 1-MONTH 變動而非 1-DAY,因為 meta.previousClose 在 range=1mo 時返回了圖表起始價格。"

→ 測試:

assert('aggregate', '1-day 變動是從 closes[] 計算,而非 meta.previousClose',
  computeChange({
    chart: { result: [{ meta: { previousClose: 100 }, indicators: { quote: [{ close: [100, 98, 99, 105] }] } }] }
  }) === ((105 - 99) / 99) * 100,
  'meta.previousClose 可能不可靠;必須使用 closes[-2]');

何時執行

  • 對過濾邏輯、關鍵字清單、驗證器、履歷對照表進行任何變更之前
  • 變更之後 — 確認沒有回歸問題
  • 每次新增 LL Library 條目之後 — 編寫原本可以捕捉該錯誤的測試
  • 任何新工作流程版本預部署前

狀態圖示含義

圖示含義
🟢 (綠色)0 個失敗 — 此套件通過;只有在其他檢查也通過時才能部署
🟡 (黃色)1-3 個失敗 — 修復前禁止部署
🔴 (紅色)4+ 個失敗 — 禁止部署;可能存在廣泛性問題

待處理 (⏳) 不計入紅色/黃色 — 它會單獨追蹤為待辦事項。待處理測試是覆蓋缺口:請在部署說明中列出它們。

反模式

反模式應採取的作法
對即時 API 進行測試僅使用模擬輸入 — 評估套件僅包含邏輯
跳過待處理功能(失去可見性)新增為 pass: null,並附上解釋缺少內容的詳細資訊
匯入生產程式碼完全複製 — Code 節點不共享作用域
一個巨大的測試函式每個斷言使用一個 assert() — 產生可讀的報告
錯誤修復後刪除測試永遠保留 — 這就是回歸防護
僅測試快樂路徑拒絕路徑覆蓋是價值最高的測試
僅在變更後執行在變更前 AND 後執行 — 確認你沒有引入回歸問題
在工作流程 JSON 中硬編碼聊天 ID / Token使用 $env.TELEGRAM_BOT_TOKEN / $env.TELEGRAM_CHAT_ID

預部署檢查清單

  • 評估工作流程在 < 10 秒內執行完畢
  • 所有套件已分組在報告中
  • 生產程式碼已完全複製(而非改寫)
  • 每個拒絕路徑至少 1 個測試
  • 每個套件至少 1 個「已知正常真實資料」測試
  • 待處理功能以 pass: null 表示並附上詳細資訊
  • 報告適合單一 Telegram 訊息(少於 4000 個字元)

參考資料

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相關技能

ashtonfeliciano/n8n-workflow-engineer

Build, debug, and harden n8n workflows. Use when the user is editing n8n workflow JSON, debugging silent failures, working with Code nodes, Telegram / Gmail / HTTP Request nodes, scheduled triggers, paired-item tracking, dedup with static data, or doing bulk operations via the n8n REST API. Covers v2.x UI specifics. Not for non-n8n automation.

community

hubgunter4-ops/configurador-de-nodos-n8n

Ayuda a configurar nodos de n8n con reglas de dependencia complejas y conexiones de IA. Agiliza la creación de flujos de trabajo automatizados gestionando dependencias de nodos intrincadas e integraciones de IA.

community

hubgunter4-ops/experto-en-n8n-mcp

Guía a los desarrolladores a seleccionar y configurar herramientas y formatos de nodo del Protocolo de Contexto de Modelo MCP dentro de los flujos de trabajo de n8n. Proporciona orientación estructurada para integrar herramientas MCP.

community

caiqueDeOliveira-dev/homelab

HomeLab Agent — Gerencia Home Assistant, ESP32 satellites, dispositivos Zigbee/Matter/Thread, automações físicas, cameras, sensores. Camada de decisão e execução no hardware (não orquestração de software = Automação/n8n).

community

hubgunter4-ops/experto-en-n8n-mcp

Guía a los desarrolladores a seleccionar y configurar herramientas y formatos de nodo del Protocolo de Contexto de Modelo MCP dentro de los flujos de trabajo de n8n. Proporciona orientación estructurada para integrar herramientas MCP.

community

hubgunter4-ops/experto-en-validacion-de-n8n

Corrige errores de validación de n8n consultando un catálogo de errores integrado. Optimiza el proceso de depuración, permitiendo identificar rápidamente problemas y resolver problemas de configuración del flujo de trabajo.

community