mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
26908cb677
## Fixed - **P0: Simulation Mode Runtime Guards** (TestExecutorAgent) - Requires AQE_ALLOW_SIMULATION=true environment variable - Prevents silent simulation in production environments - Throws explicit error with clear instructions - **P2: Explicit Error Handling** (RealAgentDBAdapter) - Replaced silent fallback (return 0) with explicit validation - Fails loudly with actionable error messages - Detects database corruption and schema mismatches - **P1: Test Isolation with UUID** (Integration Tests) - Replaced Date.now() with randomUUID() for database paths - Eliminates race conditions in parallel test execution - Uses OS temp directory for proper cleanup ## Changed - Updated CHANGELOG.md with v1.8.1 release notes - Updated README.md version badge and What's New section - Updated package.json version: 1.8.0 → 1.8.1 ## Documentation - Created docs/releases/v1.8.1-RELEASE-NOTES.md (comprehensive guide) - Created docs/releases/v1.8.1-SUMMARY.md (quick reference) - Created docs/releases/v1.8.1-VERIFICATION.md (test verification) - Created docs/reviews/BRUTAL-HONESTY-ISSUE-52-CODE-REVIEW.md (code review) ## Issues - Closes #52 (Technical Debt Remediation) - 6/8 fixes completed - Addresses #55 P0, P1, P2 priorities - Creates #57 for remaining work (performance optimization, adapter verification) ## Impact - Build Status: ✅ Passing (0 errors) - Runtime Safety: ✅ Improved (guards added) - Error Handling: ✅ Improved (explicit errors) - Test Isolation: ✅ Improved (UUID-based) - Breaking Changes: ❌ None (fully backward-compatible) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
364 lines
11 KiB
TypeScript
364 lines
11 KiB
TypeScript
/**
|
|
* Integration tests for TestExecutorAgent pattern storage
|
|
* Tests execution pattern storage, retrieval, and QUIC sync reporting
|
|
*/
|
|
|
|
import { TestExecutorAgent } from '../../src/agents/TestExecutorAgent';
|
|
import { AgentId } from '../../src/agents/BaseAgent';
|
|
import { SwarmMemoryManager } from '../../src/core/memory/SwarmMemoryManager';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
import * as os from 'os';
|
|
import { randomUUID } from 'crypto';
|
|
|
|
describe('TestExecutorAgent Pattern Storage', () => {
|
|
let testAgent: TestExecutorAgent;
|
|
let testDbPath: string;
|
|
let memoryManager: SwarmMemoryManager;
|
|
|
|
beforeEach(async () => {
|
|
// P1 FIX: Use UUID for guaranteed uniqueness + OS temp dir for proper cleanup
|
|
// Prevents race conditions in parallel test execution
|
|
testDbPath = path.join(os.tmpdir(), `test-executor-agentdb-${randomUUID()}.db`);
|
|
|
|
// Safety check: Verify file doesn't exist (should never happen with UUID)
|
|
if (fs.existsSync(testDbPath)) {
|
|
throw new Error(`Test database already exists: ${testDbPath}. This should not happen with UUID.`);
|
|
}
|
|
|
|
// Create agent with memory manager
|
|
const agentId: AgentId = {
|
|
id: 'test-executor-001',
|
|
type: 'test-executor',
|
|
capabilities: ['test-execution', 'pattern-learning']
|
|
};
|
|
|
|
testAgent = new TestExecutorAgent(agentId, {
|
|
frameworkConfig: {
|
|
jest: {
|
|
configPath: './jest.config.js',
|
|
testMatch: ['**/*.test.ts']
|
|
}
|
|
}
|
|
});
|
|
|
|
// Initialize memory manager
|
|
memoryManager = new SwarmMemoryManager(testDbPath);
|
|
await memoryManager.initialize();
|
|
|
|
// Set up agent with memory
|
|
(testAgent as any).memoryStore = memoryManager;
|
|
});
|
|
|
|
afterEach(async () => {
|
|
// Cleanup test database
|
|
if (fs.existsSync(testDbPath)) {
|
|
fs.unlinkSync(testDbPath);
|
|
}
|
|
});
|
|
|
|
describe('Execution Pattern Storage', () => {
|
|
it('should store execution patterns after successful test run', async () => {
|
|
const testResult = {
|
|
framework: 'jest',
|
|
passed: 15,
|
|
failed: 0,
|
|
skipped: 2,
|
|
total: 17,
|
|
duration: 2500,
|
|
coverage: {
|
|
lines: 85.5,
|
|
branches: 78.3,
|
|
functions: 90.2,
|
|
statements: 84.7
|
|
},
|
|
testFiles: ['user.test.ts', 'auth.test.ts']
|
|
};
|
|
|
|
// Store execution patterns
|
|
await (testAgent as any).storeExecutionPatternsInAgentDB(testResult);
|
|
|
|
// Verify patterns were stored
|
|
const patterns = await memoryManager.queryPatternsByAgent('test-executor-001', 0);
|
|
expect(patterns.length).toBeGreaterThan(0);
|
|
|
|
// Verify pattern metadata contains test execution data
|
|
const pattern = patterns[0];
|
|
const metadata = JSON.parse(pattern.metadata);
|
|
expect(metadata.agent_id).toBe('test-executor-001');
|
|
expect(metadata.framework).toBe('jest');
|
|
expect(metadata.testCount).toBe(17);
|
|
});
|
|
|
|
it('should store patterns with high confidence for passing tests', async () => {
|
|
const successResult = {
|
|
framework: 'jest',
|
|
passed: 50,
|
|
failed: 0,
|
|
total: 50,
|
|
duration: 5000
|
|
};
|
|
|
|
await (testAgent as any).storeExecutionPatternsInAgentDB(successResult);
|
|
|
|
const patterns = await memoryManager.queryPatternsByAgent('test-executor-001', 0);
|
|
expect(patterns.length).toBeGreaterThan(0);
|
|
|
|
// 100% pass rate should have high confidence
|
|
const pattern = patterns[0];
|
|
expect(pattern.confidence).toBeGreaterThanOrEqual(0.8);
|
|
});
|
|
|
|
it('should store patterns with lower confidence for failing tests', async () => {
|
|
const failureResult = {
|
|
framework: 'jest',
|
|
passed: 10,
|
|
failed: 15,
|
|
total: 25,
|
|
duration: 3000
|
|
};
|
|
|
|
await (testAgent as any).storeExecutionPatternsInAgentDB(failureResult);
|
|
|
|
const patterns = await memoryManager.queryPatternsByAgent('test-executor-001', 0);
|
|
expect(patterns.length).toBeGreaterThan(0);
|
|
|
|
// 40% pass rate should have lower confidence
|
|
const pattern = patterns[0];
|
|
expect(pattern.confidence).toBeLessThan(0.6);
|
|
});
|
|
});
|
|
|
|
describe('Pattern Retrieval Before Execution', () => {
|
|
it('should retrieve historical execution patterns before running tests', async () => {
|
|
// Store historical pattern
|
|
await memoryManager.storePattern({
|
|
id: 'historical-pattern-001',
|
|
pattern: 'jest:execution:success',
|
|
confidence: 0.9,
|
|
usageCount: 10,
|
|
metadata: {
|
|
agent_id: 'test-executor-001',
|
|
framework: 'jest',
|
|
avgDuration: 2500,
|
|
avgPassRate: 0.95
|
|
}
|
|
});
|
|
|
|
// Retrieve patterns
|
|
const patterns = await memoryManager.queryPatternsByAgent('test-executor-001', 0.8);
|
|
|
|
expect(patterns.length).toBe(1);
|
|
expect(patterns[0].confidence).toBe(0.9);
|
|
|
|
const metadata = JSON.parse(patterns[0].metadata);
|
|
expect(metadata.framework).toBe('jest');
|
|
});
|
|
|
|
it('should filter patterns by minimum confidence threshold', async () => {
|
|
// Store patterns with varying confidence
|
|
await memoryManager.storePattern({
|
|
id: 'high-conf-pattern',
|
|
pattern: 'jest:reliable',
|
|
confidence: 0.95,
|
|
usageCount: 20,
|
|
metadata: { agent_id: 'test-executor-001' }
|
|
});
|
|
|
|
await memoryManager.storePattern({
|
|
id: 'low-conf-pattern',
|
|
pattern: 'jest:unreliable',
|
|
confidence: 0.3,
|
|
usageCount: 2,
|
|
metadata: { agent_id: 'test-executor-001' }
|
|
});
|
|
|
|
// Query with confidence threshold 0.8
|
|
const highConfPatterns = await memoryManager.queryPatternsByAgent('test-executor-001', 0.8);
|
|
|
|
expect(highConfPatterns.length).toBe(1);
|
|
expect(highConfPatterns[0].id).toBe('high-conf-pattern');
|
|
});
|
|
});
|
|
|
|
describe('Mock vs Real Adapter Behavior', () => {
|
|
it('should handle mock adapter in test environment', () => {
|
|
process.env.NODE_ENV = 'test';
|
|
|
|
const isReal = (testAgent as any).isRealAgentDB();
|
|
expect(isReal).toBe(false);
|
|
|
|
// Mock adapter should not affect test execution
|
|
});
|
|
|
|
it('should use real adapter when configured', async () => {
|
|
// Set up real adapter environment
|
|
delete process.env.NODE_ENV;
|
|
delete process.env.JEST_WORKER_ID;
|
|
process.env.AQE_USE_MOCK_AGENTDB = 'false';
|
|
|
|
// Pattern storage should work with real adapter
|
|
const testResult = {
|
|
framework: 'jest',
|
|
passed: 10,
|
|
failed: 0,
|
|
total: 10,
|
|
duration: 1000
|
|
};
|
|
|
|
await expect((testAgent as any).storeExecutionPatternsInAgentDB(testResult))
|
|
.resolves.not.toThrow();
|
|
|
|
// Restore environment
|
|
process.env.NODE_ENV = 'test';
|
|
});
|
|
});
|
|
|
|
describe('QUIC Sync Reporting', () => {
|
|
it('should report QUIC sync status when real AgentDB is used', async () => {
|
|
// This test verifies that QUIC sync logging is conditional
|
|
// In mock mode, QUIC sync should not be reported
|
|
|
|
process.env.NODE_ENV = 'test'; // Mock mode
|
|
|
|
const testResult = {
|
|
framework: 'jest',
|
|
passed: 10,
|
|
failed: 0,
|
|
total: 10,
|
|
duration: 1000
|
|
};
|
|
|
|
// Store patterns (should not log QUIC sync in mock mode)
|
|
await (testAgent as any).storeExecutionPatternsInAgentDB(testResult);
|
|
|
|
// No QUIC sync should be reported in mock mode
|
|
// This is verified through logging - in real implementation,
|
|
// we'd capture console output to verify
|
|
});
|
|
});
|
|
|
|
describe('Pattern Embedding Generation', () => {
|
|
it('should generate embeddings for execution patterns', async () => {
|
|
const testResult = {
|
|
framework: 'jest',
|
|
passed: 20,
|
|
failed: 1,
|
|
total: 21,
|
|
duration: 3000
|
|
};
|
|
|
|
// Spy on embedding generation
|
|
const createEmbeddingSpy = jest.spyOn(testAgent as any, 'createExecutionPatternEmbedding');
|
|
|
|
await (testAgent as any).storeExecutionPatternsInAgentDB(testResult);
|
|
|
|
// Verify embedding was created
|
|
expect(createEmbeddingSpy).toHaveBeenCalled();
|
|
|
|
createEmbeddingSpy.mockRestore();
|
|
});
|
|
|
|
it('should generate consistent embeddings for similar patterns', async () => {
|
|
const pattern1 = { framework: 'jest', passed: 10, total: 10 };
|
|
const pattern2 = { framework: 'jest', passed: 10, total: 10 };
|
|
|
|
const embedding1 = await (testAgent as any).createExecutionPatternEmbedding(pattern1);
|
|
const embedding2 = await (testAgent as any).createExecutionPatternEmbedding(pattern2);
|
|
|
|
// Same pattern should generate identical embeddings
|
|
expect(embedding1).toEqual(embedding2);
|
|
});
|
|
});
|
|
|
|
describe('Error Handling', () => {
|
|
it('should handle pattern storage failures gracefully', async () => {
|
|
// Close database to simulate failure
|
|
await memoryManager.close();
|
|
|
|
const testResult = {
|
|
framework: 'jest',
|
|
passed: 10,
|
|
failed: 0,
|
|
total: 10,
|
|
duration: 1000
|
|
};
|
|
|
|
// Should not throw even if storage fails
|
|
await expect((testAgent as any).storeExecutionPatternsInAgentDB(testResult))
|
|
.resolves.not.toThrow();
|
|
});
|
|
|
|
it('should handle pattern retrieval failures gracefully', async () => {
|
|
// Close database to simulate failure
|
|
await memoryManager.close();
|
|
|
|
// Should not throw even if retrieval fails
|
|
await expect(memoryManager.queryPatternsByAgent('test-executor-001', 0))
|
|
.rejects.toThrow();
|
|
|
|
// Agent should continue execution despite retrieval failure
|
|
});
|
|
|
|
it('should continue test execution if AgentDB fails', async () => {
|
|
// Simulate AgentDB failure
|
|
(testAgent as any).memoryStore = null;
|
|
|
|
const testResult = {
|
|
framework: 'jest',
|
|
passed: 5,
|
|
failed: 0,
|
|
total: 5,
|
|
duration: 500
|
|
};
|
|
|
|
// Test execution should complete even if pattern storage fails
|
|
await expect((testAgent as any).storeExecutionPatternsInAgentDB(testResult))
|
|
.resolves.not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('Framework-Specific Pattern Storage', () => {
|
|
it('should store framework-specific metadata for Jest', async () => {
|
|
const jestResult = {
|
|
framework: 'jest',
|
|
passed: 25,
|
|
failed: 2,
|
|
total: 27,
|
|
duration: 4500,
|
|
coverage: {
|
|
lines: 88.5,
|
|
branches: 82.0,
|
|
functions: 91.5,
|
|
statements: 87.3
|
|
}
|
|
};
|
|
|
|
await (testAgent as any).storeExecutionPatternsInAgentDB(jestResult);
|
|
|
|
const patterns = await memoryManager.queryPatternsByAgent('test-executor-001', 0);
|
|
const metadata = JSON.parse(patterns[0].metadata);
|
|
|
|
expect(metadata.framework).toBe('jest');
|
|
expect(metadata.coverage).toBeDefined();
|
|
});
|
|
|
|
it('should store framework-specific metadata for Mocha', async () => {
|
|
const mochaResult = {
|
|
framework: 'mocha',
|
|
passed: 30,
|
|
failed: 1,
|
|
total: 31,
|
|
duration: 3200
|
|
};
|
|
|
|
await (testAgent as any).storeExecutionPatternsInAgentDB(mochaResult);
|
|
|
|
const patterns = await memoryManager.queryPatternsByAgent('test-executor-001', 0);
|
|
const metadata = JSON.parse(patterns[0].metadata);
|
|
|
|
expect(metadata.framework).toBe('mocha');
|
|
});
|
|
});
|
|
});
|