From a12e782225fd5b106a2f7a713c2eafb5768f19a2 Mon Sep 17 00:00:00 2001 From: shortstacked Date: Tue, 2 Sep 2025 18:30:49 +0100 Subject: [PATCH] test: Add baseline memory test (#19102) --- .../containers/n8n-test-container-creation.ts | 1 + .../testing/playwright/playwright.config.ts | 2 +- .../memory-consumption-cloud.spec.ts | 29 ++++++++++++++ .../playwright/utils/performance-helper.ts | 39 +++++++++++++++++++ 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 packages/testing/playwright/tests/performance/memory-consumption-cloud.spec.ts diff --git a/packages/testing/containers/n8n-test-container-creation.ts b/packages/testing/containers/n8n-test-container-creation.ts index 952ba0c958..a8fe1e800d 100644 --- a/packages/testing/containers/n8n-test-container-creation.ts +++ b/packages/testing/containers/n8n-test-container-creation.ts @@ -42,6 +42,7 @@ const BASE_ENV: Record = { E2E_TESTS: 'false', QUEUE_HEALTH_CHECK_ACTIVE: 'true', N8N_DIAGNOSTICS_ENABLED: 'false', + N8N_METRICS: 'true', N8N_RUNNERS_ENABLED: 'true', NODE_ENV: 'development', // If this is set to test, the n8n container will not start, insights module is not found?? N8N_LICENSE_TENANT_ID: process.env.N8N_LICENSE_TENANT_ID ?? '1001', diff --git a/packages/testing/playwright/playwright.config.ts b/packages/testing/playwright/playwright.config.ts index 9740fee7c7..1a8e8ab7f3 100644 --- a/packages/testing/playwright/playwright.config.ts +++ b/packages/testing/playwright/playwright.config.ts @@ -71,5 +71,5 @@ export default defineConfig({ currentsReporter(currentsConfig), ['./reporters/metrics-reporter.ts'], ] - : [['html'], ['./reporters/metrics-reporter.ts']], + : [['html'], ['./reporters/metrics-reporter.ts'], ['list']], }); diff --git a/packages/testing/playwright/tests/performance/memory-consumption-cloud.spec.ts b/packages/testing/playwright/tests/performance/memory-consumption-cloud.spec.ts new file mode 100644 index 0000000000..10a552965f --- /dev/null +++ b/packages/testing/playwright/tests/performance/memory-consumption-cloud.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '../../fixtures/cloud'; +import { attachMetric, pollMemoryMetric } from '../../utils/performance-helper'; + +test.describe('Memory Consumption', () => { + const CONTAINER_STABILIZATION_TIME = 20000; + const POLL_MEMORY_DURATION = 30000; + const STARTER_PLAN_MEMORY_LIMIT = 768; + + test('Memory consumption baseline with starter plan resources @cloud:starter', async ({ + cloudContainer, + }, testInfo) => { + // Wait for container to stabilize + await new Promise((resolve) => setTimeout(resolve, CONTAINER_STABILIZATION_TIME)); + + // Poll memory metric for 30 seconds to get baseline + const averageMemoryBytes = await pollMemoryMetric( + cloudContainer.baseUrl, + POLL_MEMORY_DURATION, + 1000, + ); + const averageMemoryMB = averageMemoryBytes / 1024 / 1024; + + await attachMetric(testInfo, 'memory-consumption-baseline', averageMemoryMB, 'MB'); + + // Verify memory is within starter plan limits (768MB) + expect(averageMemoryMB).toBeLessThan(STARTER_PLAN_MEMORY_LIMIT); + expect(averageMemoryMB).toBeGreaterThan(100); + }); +}); diff --git a/packages/testing/playwright/utils/performance-helper.ts b/packages/testing/playwright/utils/performance-helper.ts index 1ce92c371b..5f66df1302 100644 --- a/packages/testing/playwright/utils/performance-helper.ts +++ b/packages/testing/playwright/utils/performance-helper.ts @@ -29,6 +29,45 @@ export async function getAllPerformanceMetrics(page: Page) { }); } +/** + * Polls the memory metric from Prometheus endpoint and calculates average + * @param baseUrl - The base URL of the n8n instance + * @param durationMs - How long to poll in milliseconds + * @param intervalMs - Interval between polls in milliseconds + * @returns Average memory consumption in bytes + */ +export async function pollMemoryMetric( + baseUrl: string, + durationMs: number = 30000, + intervalMs: number = 1000, +): Promise { + const samples: number[] = []; + const startTime = Date.now(); + + while (Date.now() - startTime < durationMs) { + try { + const response = await fetch(`${baseUrl}/metrics`); + const metricsText = await response.text(); + + const memoryMatch = metricsText.match(/n8n_process_resident_memory_bytes\s+(\d+(?:\.\d+)?)/); + if (memoryMatch) { + const memoryBytes = parseFloat(memoryMatch[1]); + samples.push(memoryBytes); + } + } catch (error) { + console.error('Error polling memory metric:', error); + } + + await new Promise((resolve) => setTimeout(resolve, intervalMs)); + } + + if (samples.length === 0) { + throw new Error('No memory samples collected'); + } + + return samples.reduce((sum, sample) => sum + sample, 0) / samples.length; +} + /** * Attach a performance metric for collection by the metrics reporter * @param testInfo - The Playwright TestInfo object