mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
5a2883a4a0
Agentic Quality Engineering Fleet - AI-driven quality management platform Features: - 16 specialized QE agents for comprehensive testing - AI-powered test generation with 95% coverage targets - O(log n) sublinear algorithms for massive scale - Parallel test execution with intelligent orchestration - Real-time coverage analysis and gap detection - Smart quality gates with ML-driven decisions - Security scanning (SAST, DAST, dependency analysis) - Performance testing with load orchestration - Flaky test detection with automatic stabilization - API contract validation with breaking change detection - Test data generation (10,000+ records/sec) - Production intelligence (convert incidents to tests) - Chaos engineering for resilience testing - MCP integration with Claude Code - Multi-framework support (Jest, Mocha, Cypress, Playwright) Architecture: - TypeScript implementation - MCP (Model Context Protocol) integration - Claude Code agent orchestration - Event-driven agent coordination - Distributed fleet management - Cross-session memory persistence Documentation: - Complete API documentation (TypeDoc) - User guides (Getting Started, MCP Integration, Test Generation, etc.) - Architecture deep-dive - CLI reference - Contributing guidelines - MIT License Tech Stack: - TypeScript 5.3+ - Node.js 18+ - @anthropic-ai/sdk ^0.64.0 - @modelcontextprotocol/sdk ^1.18.2 - Jest for testing - Winston for logging - SQLite for persistence Project Structure: - src/ - Source code (agents, core, MCP, CLI) - tests/ - Comprehensive test suite - docs/ - Complete documentation - .claude/ - Agent definitions and commands - config/ - Configuration files 🤖 Generated with Claude Code https://claude.com/claude-code Co-Authored-By: Claude <noreply@anthropic.com>
277 lines
8.5 KiB
TypeScript
277 lines
8.5 KiB
TypeScript
import { jest } from '@jest/globals';
|
|
|
|
// London School TDD setup - Mock-first, behavior-driven testing patterns
|
|
// This file provides utilities and patterns for London School TDD approach
|
|
|
|
// London School TDD utilities
|
|
global.londonSchool = {
|
|
// Create mock with verification helpers
|
|
createMock: <T>(name: string, implementation?: Partial<T>): jest.Mocked<T> & { _mockName: string } => {
|
|
const mock = {
|
|
_mockName: name,
|
|
...implementation
|
|
} as jest.Mocked<T> & { _mockName: string };
|
|
|
|
// Track mock for verification
|
|
if (!global.activeMocks) {
|
|
global.activeMocks = new Set();
|
|
}
|
|
global.activeMocks.add(mock);
|
|
|
|
return mock;
|
|
},
|
|
|
|
// Verify all mocks were used (London School principle)
|
|
verifyAllMocksUsed: () => {
|
|
if (!global.activeMocks) return;
|
|
|
|
const unusedMocks: string[] = [];
|
|
global.activeMocks.forEach((mock: any) => {
|
|
if (mock._mockName && !mock._verified) {
|
|
unusedMocks.push(mock._mockName);
|
|
}
|
|
});
|
|
|
|
if (unusedMocks.length > 0) {
|
|
console.warn(`London School TDD: Unused mocks detected: ${unusedMocks.join(', ')}`);
|
|
}
|
|
},
|
|
|
|
// Verify interaction patterns (how objects collaborate)
|
|
verifyInteractionPattern: (mocks: jest.Mocked<any>[], expectedPattern: string[]) => {
|
|
const callOrder: string[] = [];
|
|
|
|
mocks.forEach(mock => {
|
|
Object.keys(mock).forEach(method => {
|
|
if (jest.isMockFunction(mock[method])) {
|
|
const calls = mock[method].mock.calls;
|
|
calls.forEach((call, index) => {
|
|
callOrder.push(`${mock._mockName || 'unknown'}.${method}`);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
expect(callOrder).toEqual(expectedPattern);
|
|
},
|
|
|
|
// Create contract mock (interface verification)
|
|
createContractMock: <T>(contractName: string, requiredMethods: string[]): jest.Mocked<T> => {
|
|
const mock = {} as jest.Mocked<T>;
|
|
|
|
requiredMethods.forEach(method => {
|
|
(mock as any)[method] = jest.fn().mockName(`${contractName}.${method}`);
|
|
});
|
|
|
|
// Add contract verification
|
|
(mock as any)._verifyContract = () => {
|
|
requiredMethods.forEach(method => {
|
|
expect(mock[method as keyof T]).toBeDefined();
|
|
expect(jest.isMockFunction(mock[method as keyof T])).toBe(true);
|
|
});
|
|
};
|
|
|
|
return mock;
|
|
},
|
|
|
|
// Verify test follows London School principles
|
|
verifyLondonSchoolPrinciples: (testMetadata: {
|
|
mocksUsed: number;
|
|
stateVerification: boolean;
|
|
behaviorVerification: boolean;
|
|
interactionTesting: boolean;
|
|
}) => {
|
|
// London School tests should:
|
|
// 1. Use mocks for all dependencies
|
|
expect(testMetadata.mocksUsed).toBeGreaterThan(0);
|
|
|
|
// 2. Focus on behavior, not state
|
|
expect(testMetadata.behaviorVerification).toBe(true);
|
|
|
|
// 3. Test interactions between objects
|
|
expect(testMetadata.interactionTesting).toBe(true);
|
|
|
|
// 4. Minimize state verification
|
|
if (testMetadata.stateVerification) {
|
|
console.warn('London School TDD: Consider focusing on behavior rather than state');
|
|
}
|
|
},
|
|
|
|
// Mock collaboration builder
|
|
mockCollaboration: (collaborators: Array<{ name: string; methods: string[] }>) => {
|
|
const mocks: Record<string, jest.Mocked<any>> = {};
|
|
|
|
collaborators.forEach(({ name, methods }) => {
|
|
mocks[name] = global.londonSchool.createContractMock(name, methods);
|
|
});
|
|
|
|
return {
|
|
mocks,
|
|
verifyCollaboration: (expectedInteractions: Array<{ mock: string; method: string; args?: any[] }>) => {
|
|
expectedInteractions.forEach(({ mock, method, args }) => {
|
|
const mockObj = mocks[mock];
|
|
expect(mockObj[method]).toHaveBeenCalled();
|
|
|
|
if (args) {
|
|
expect(mockObj[method]).toHaveBeenCalledWith(...args);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
},
|
|
|
|
// Test doubles factory
|
|
createTestDoubles: {
|
|
// Dummy - objects passed around but never used
|
|
dummy: <T>(type: string): T => {
|
|
return { _type: `dummy-${type}` } as T;
|
|
},
|
|
|
|
// Fake - working implementation but not suitable for production
|
|
fake: <T>(type: string, implementation: Partial<T>): T => {
|
|
return {
|
|
_type: `fake-${type}`,
|
|
...implementation
|
|
} as T;
|
|
},
|
|
|
|
// Stub - provides canned answers to calls
|
|
stub: <T>(type: string, responses: Record<string, any>): jest.Mocked<T> => {
|
|
const stub = {} as jest.Mocked<T>;
|
|
|
|
Object.entries(responses).forEach(([method, response]) => {
|
|
(stub as any)[method] = jest.fn().mockReturnValue(response);
|
|
});
|
|
|
|
(stub as any)._type = `stub-${type}`;
|
|
return stub;
|
|
},
|
|
|
|
// Spy - records information about how they were called
|
|
spy: <T>(type: string, implementation?: Partial<T>): jest.Mocked<T> => {
|
|
const spy = { ...implementation } as jest.Mocked<T>;
|
|
|
|
Object.keys(implementation || {}).forEach(method => {
|
|
if (typeof (spy as any)[method] === 'function') {
|
|
(spy as any)[method] = jest.fn((spy as any)[method]);
|
|
}
|
|
});
|
|
|
|
(spy as any)._type = `spy-${type}`;
|
|
return spy;
|
|
},
|
|
|
|
// Mock - pre-programmed with expectations
|
|
mock: <T>(type: string, expectations: Record<string, { args?: any[]; returns?: any; throws?: Error }>): jest.Mocked<T> => {
|
|
const mock = {} as jest.Mocked<T>;
|
|
|
|
Object.entries(expectations).forEach(([method, expectation]) => {
|
|
const mockFn = jest.fn();
|
|
|
|
if (expectation.throws) {
|
|
mockFn.mockRejectedValue(expectation.throws);
|
|
} else {
|
|
mockFn.mockReturnValue(expectation.returns);
|
|
}
|
|
|
|
(mock as any)[method] = mockFn;
|
|
});
|
|
|
|
(mock as any)._type = `mock-${type}`;
|
|
return mock;
|
|
}
|
|
}
|
|
};
|
|
|
|
// London School test patterns
|
|
global.testPatterns = {
|
|
// Outside-In TDD pattern
|
|
outsideIn: {
|
|
// Start with acceptance test
|
|
givenAcceptanceCriteria: (criteria: string) => {
|
|
return {
|
|
when: (action: string) => ({
|
|
then: (expectation: string) => {
|
|
// Framework for outside-in TDD
|
|
console.log(`Given: ${criteria}`);
|
|
console.log(`When: ${action}`);
|
|
console.log(`Then: ${expectation}`);
|
|
}
|
|
})
|
|
};
|
|
}
|
|
},
|
|
|
|
// Collaboration testing pattern
|
|
collaboration: {
|
|
between: (collaborators: string[]) => ({
|
|
should: (behavior: string) => ({
|
|
when: (scenario: string) => {
|
|
return {
|
|
collaborators,
|
|
behavior,
|
|
scenario,
|
|
verify: (verificationFn: () => void) => verificationFn()
|
|
};
|
|
}
|
|
})
|
|
})
|
|
},
|
|
|
|
// Interaction testing pattern
|
|
interaction: {
|
|
verify: (description: string, verificationFn: () => void) => {
|
|
it(`should verify interaction: ${description}`, verificationFn);
|
|
},
|
|
|
|
sequence: (description: string, mocks: jest.Mocked<any>[], expectedSequence: string[]) => {
|
|
it(`should follow interaction sequence: ${description}`, () => {
|
|
global.londonSchool.verifyInteractionPattern(mocks, expectedSequence);
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
// Track active mocks for verification
|
|
global.activeMocks = new Set();
|
|
|
|
// Clean up mocks after each test
|
|
afterEach(() => {
|
|
global.londonSchool.verifyAllMocksUsed();
|
|
global.activeMocks?.clear();
|
|
});
|
|
|
|
// Declare global types
|
|
declare global {
|
|
var londonSchool: {
|
|
createMock: <T>(name: string, implementation?: Partial<T>) => jest.Mocked<T> & { _mockName: string };
|
|
verifyAllMocksUsed: () => void;
|
|
verifyInteractionPattern: (mocks: jest.Mocked<any>[], expectedPattern: string[]) => void;
|
|
createContractMock: <T>(contractName: string, requiredMethods: string[]) => jest.Mocked<T>;
|
|
verifyLondonSchoolPrinciples: (testMetadata: any) => void;
|
|
mockCollaboration: (collaborators: Array<{ name: string; methods: string[] }>) => any;
|
|
createTestDoubles: {
|
|
dummy: <T>(type: string) => T;
|
|
fake: <T>(type: string, implementation: Partial<T>) => T;
|
|
stub: <T>(type: string, responses: Record<string, any>) => jest.Mocked<T>;
|
|
spy: <T>(type: string, implementation?: Partial<T>) => jest.Mocked<T>;
|
|
mock: <T>(type: string, expectations: Record<string, any>) => jest.Mocked<T>;
|
|
};
|
|
};
|
|
|
|
var testPatterns: {
|
|
outsideIn: {
|
|
givenAcceptanceCriteria: (criteria: string) => any;
|
|
};
|
|
collaboration: {
|
|
between: (collaborators: string[]) => any;
|
|
};
|
|
interaction: {
|
|
verify: (description: string, verificationFn: () => void) => void;
|
|
sequence: (description: string, mocks: jest.Mocked<any>[], expectedSequence: string[]) => void;
|
|
};
|
|
};
|
|
|
|
var activeMocks: Set<any>;
|
|
}
|