Skip to main content
Glama
ooples

MCP Console Automation Server

FlakeDetector.test.ts7.75 kB
/** * Tests for FlakeDetector */ import { FlakeDetector } from '../testing/FlakeDetector.js'; import { TestDefinition, TestResult } from '../types/test-framework.js'; describe('FlakeDetector', () => { let detector: FlakeDetector; beforeEach(() => { detector = new FlakeDetector(); }); describe('Flake Detection', () => { it('should detect flaky test with inconsistent results', async () => { let callCount = 0; const test: TestDefinition = { name: 'flaky-test', assertions: [], timeout: 100, retry: 0, }; const executor = async (t: TestDefinition): Promise<TestResult> => { callCount++; const passed = callCount % 2 === 0; // Alternates pass/fail return { test: t, status: passed ? 'pass' : 'fail', duration: 10, startTime: Date.now(), endTime: Date.now() + 10, assertions: [], error: passed ? undefined : new Error('Flaky failure'), }; }; const report = await detector.detectFlake(test, executor, { runs: 10, threshold: 0.1, parallel: false, }); expect(report.testName).toBe('flaky-test'); expect(report.totalRuns).toBe(10); expect(report.passes).toBe(5); expect(report.failures).toBe(5); expect(report.flakeRate).toBe(0.5); expect(report.isFlaky).toBe(true); }); it('should mark stable test as not flaky', async () => { const test: TestDefinition = { name: 'stable-test', assertions: [], timeout: 100, retry: 0, }; const executor = async (t: TestDefinition): Promise<TestResult> => ({ test: t, status: 'pass', duration: 10, startTime: Date.now(), endTime: Date.now() + 10, assertions: [], }); const report = await detector.detectFlake(test, executor, { runs: 10, threshold: 0.1, parallel: false, }); expect(report.isFlaky).toBe(false); expect(report.flakeRate).toBe(0); }); it('should detect flaky test with occasional failures', async () => { let callCount = 0; const test: TestDefinition = { name: 'occasionally-flaky', assertions: [], timeout: 100, retry: 0, }; const executor = async (t: TestDefinition): Promise<TestResult> => { callCount++; const passed = callCount !== 3 && callCount !== 7; // Fails on 3rd and 7th run return { test: t, status: passed ? 'pass' : 'fail', duration: 10, startTime: Date.now(), endTime: Date.now() + 10, assertions: [], error: passed ? undefined : new Error('Occasional failure'), }; }; const report = await detector.detectFlake(test, executor, { runs: 10, threshold: 0.1, parallel: false, }); expect(report.totalRuns).toBe(10); expect(report.failures).toBe(2); expect(report.flakeRate).toBe(0.2); expect(report.isFlaky).toBe(true); }); }); describe('Failure Patterns', () => { it('should extract failure patterns', async () => { let callCount = 0; const test: TestDefinition = { name: 'pattern-test', assertions: [], timeout: 100, retry: 0, }; const executor = async (t: TestDefinition): Promise<TestResult> => { callCount++; const errorType = callCount % 2 === 0 ? 'timeout' : 'assertion failed'; return { test: t, status: 'fail', duration: 10, startTime: Date.now(), endTime: Date.now() + 10, assertions: [], error: new Error(errorType), }; }; const report = await detector.detectFlake(test, executor, { runs: 10, threshold: 0, parallel: false, }); expect(report.failurePatterns).toBeDefined(); expect(report.failurePatterns!.length).toBeGreaterThan(0); }); }); describe('Batch Flake Detection', () => { it('should detect multiple flaky tests', async () => { const tests: TestDefinition[] = [ { name: 'stable', assertions: [], timeout: 100, retry: 0 }, { name: 'flaky-1', assertions: [], timeout: 100, retry: 0 }, { name: 'flaky-2', assertions: [], timeout: 100, retry: 0 }, ]; const executor = async (t: TestDefinition): Promise<TestResult> => { const isFlaky = t.name.includes('flaky'); const passed = !isFlaky || Math.random() > 0.3; return { test: t, status: passed ? 'pass' : 'fail', duration: 10, startTime: Date.now(), endTime: Date.now() + 10, assertions: [], error: passed ? undefined : new Error('Flaky'), }; }; const reports = await detector.detectFlakyTests(tests, executor, { runs: 10, threshold: 0.2, parallel: false, }); expect(reports.length).toBeGreaterThan(0); reports.forEach((r) => { expect(r.isFlaky).toBe(true); }); }); }); describe('Flake Summary', () => { it('should generate summary for multiple tests', async () => { const reports = [ { testName: 'test-1', totalRuns: 10, passes: 7, failures: 3, errors: 0, flakeRate: 0.3, isFlaky: true, threshold: 0.1, }, { testName: 'test-2', totalRuns: 10, passes: 9, failures: 1, errors: 0, flakeRate: 0.1, isFlaky: false, threshold: 0.1, }, ]; const summary = detector.generateFlakeSummary(reports); expect(summary.totalTests).toBe(2); expect(summary.flakyTests).toBe(1); expect(summary.stableTests).toBe(1); expect(summary.flakeRate).toBe(0.5); }); }); describe('Recommendations', () => { it('should generate recommendations for flaky tests', () => { const report = { testName: 'timeout-test', totalRuns: 10, passes: 6, failures: 4, errors: 0, flakeRate: 0.4, isFlaky: true, threshold: 0.1, failurePatterns: ['Timeout (4 times)'], }; const recommendations = detector.generateRecommendations(report); expect(recommendations.length).toBeGreaterThan(0); expect(recommendations.some((r) => r.includes('timeout'))).toBe(true); }); }); describe('Parallel vs Sequential Detection', () => { it('should run detection in parallel when configured', async () => { const test: TestDefinition = { name: 'parallel-test', assertions: [], timeout: 100, retry: 0, }; const executor = async (t: TestDefinition): Promise<TestResult> => ({ test: t, status: Math.random() > 0.5 ? 'pass' : 'fail', duration: 50, startTime: Date.now(), endTime: Date.now() + 50, assertions: [], }); const startParallel = Date.now(); await detector.detectFlake(test, executor, { runs: 10, threshold: 0.1, parallel: true, }); const parallelDuration = Date.now() - startParallel; const startSequential = Date.now(); await detector.detectFlake(test, executor, { runs: 10, threshold: 0.1, parallel: false, }); const sequentialDuration = Date.now() - startSequential; // Parallel should be faster expect(parallelDuration).toBeLessThan(sequentialDuration); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ooples/mcp-console-automation'

If you have feedback or need assistance with the MCP directory API, please join our Discord server