Performance tests can be notoriously brittle and unreliable across different hardware, operating systems, and CI environments. This document outlines the strategies implemented in Marjoram to create robust performance tests.
Before (Brittle):
const start = performance.now();
performOperation();
const duration = performance.now() - start;
expect(duration).toBeLessThan(100); // Fixed threshold - fails on slow systems
After (Robust):
const testOperation = () => {
const start = performance.now();
performOperation();
return performance.now() - start;
};
const baselineOperation = () => {
const start = performance.now();
simpleEquivalentOperation();
return performance.now() - start;
};
const ratio = testOperation() / baselineOperation();
expect(ratio).toBeLessThan(10); // Relative performance - more reliable
const performanceBenchmark = (testFn, baselineFn, iterations = 3) => {
const testTimes = [];
const baselineTimes = [];
for (let i = 0; i < iterations; i++) {
testTimes.push(testFn());
baselineTimes.push(baselineFn());
}
const avgTest = testTimes.reduce((a, b) => a + b) / iterations;
const avgBaseline = baselineTimes.reduce((a, b) => a + b) / iterations;
return avgTest / avgBaseline;
};
const isCI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS === 'true';
const PERF_CONFIG = {
skipTimingTests: isCI || isSlow,
maxRatio: isCI ? 20 : 10, // More lenient in CI
iterations: isCI ? 1 : 3 // Fewer iterations in CI
};
// Skip timing-sensitive tests in unreliable environments
const testFn = PERF_CONFIG.skipTimingTests ? test.skip : test;
testFn("should handle rapid updates efficiently", () => {
// Test only runs in reliable environments
});
// Log performance metrics for debugging CI issues
console.log(`Test=${testTime.toFixed(2)}ms, Baseline=${baselineTime.toFixed(2)}ms, Ratio=${ratio.toFixed(2)}`);
expect(time).toBeLessThan(100))The performance test configuration can be customized via environment variables:
# Skip all timing-sensitive tests
CI=true npm test
# Force run all tests (use with caution in CI)
FORCE_PERF_TESTS=true npm test
# Adjust performance ratio tolerance
PERF_RATIO_TOLERANCE=15 npm test
For continuous performance monitoring, consider:
See __tests__/edge-cases/performance.test.ts for a complete implementation of these patterns.
In GitHub Actions, performance tests are automatically adjusted:
- name: Run Tests
run: npm test
env:
CI: true # Automatically set by GitHub Actions
The tests will automatically: