mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
1e3fbb5ea8
* SwarmMemoryManager Refactoring Plan * fix: add missing directories to npm package (v1.9.3) Added templates/, .claude/helpers/, and docs/reference/ to package.json files array. These were missing from the npm distribution, causing `aqe init` to fail with "Template file not found" errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * checkpoint improvements * fix: critical memory/learning system fixes for v1.9.4 ## Critical Fixes - Vector embeddings now stored correctly (was storing NULL) - SQL parameter style fixed for agentdb's SqlJsDatabase wrapper - HNSW index schema mismatch resolved with pattern_id column - Hooks now save to correct database (.agentic-qe/agentdb.db) ## New Features - Added 5 SwarmMemoryManager methods for learning data retrieval: - getBestAction() - Q-learning best action selection - getRecentLearningExperiences() - Recent experience retrieval - getLearningExperiencesByTaskType() - Task-filtered experiences - getHighRewardExperiences() - Successful experience extraction - getLearningStats() - Aggregate learning statistics - Added comprehensive integration test for memory/learning loop - Added RuVector pattern store integration (experimental) ## Technical Details - Vector embeddings: 384 dimensions × 4 bytes = 1,536 bytes per pattern - All 12 integration tests pass - HNSW index: 150x faster vector search enabled 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: move ARM64-only ruvector packages to optionalDependencies Fixes CI failures caused by platform-specific dependencies: - @ruvector/node-linux-arm64-gnu (ARM64 only) - ruvector-core-linux-arm64-gnu (ARM64 only) These packages caused npm ci to fail on x64 CI runners with: "EBADPLATFORM - wanted linux/arm64, current linux/x64" Solution: Move ARM64 packages to optionalDependencies and add x64 variants for cross-platform compatibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * chore: regenerate package-lock.json with x64 ruvector packages Updates lockfile to include optional x64 platform packages for CI compatibility: - @ruvector/node-linux-x64-gnu@0.1.17 - ruvector-core-linux-x64-gnu@0.1.15 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: replace fake QUIC with proper implementation and clean up skills manifest QUIC Transport: - Remove fake HTTP/2-based QUICTransport.ts that pretended to be QUIC - Add proper QUIC implementation via Rust/WASM (@agentic-flow/quic-wasm) - Add WebSocket fallback transport for when WASM unavailable - Add dedicated type declarations for optional WASM module - Features: 0-RTT connection, stream multiplexing, TLS 1.3 built-in Skills Manifest: - Rewrite skills-manifest.json with only QE skills (41 skills) - Remove Claude Flow platform skills (agentdb-*, flow-nexus-*, github-*, etc.) - Organize into proper categories: qe-core, testing-methodologies, etc. Bug Fixes: - Fix UnifiedMemoryCoordinator.ts TypeScript errors - Use Logger.getInstance() instead of private constructor - Use swarmMemory.query() instead of non-existent list() method - Use correct close() method signatures for backends 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add QX Partner agent, compact subagents, fix CLAUDE.md dynamic counts - Add QX Partner agent for Quality Experience analysis combining QA + UX perspectives - Compact 9 subagent definitions to ~80 lines each (88% reduction) - Fix CLAUDE.md template to dynamically count agents (including subagents) and skills - Move CLAUDE.md creation after parallel phases for accurate counts - Remove 'Production-Ready' claim from README and CHANGELOG - Clean up backup files and move docs to proper directory Initialization now correctly reports: - 31 QE Agents (20 main + 11 subagents) - 53 QE Skills - 8 Slash Commands 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: resolve CI failures and security alert #36 - Replace MD5 with SHA-256 for ETag calculation (security alert #36) - Fix CRLF line endings in shell scripts causing parse errors - Remove 'local' keyword from for-loop in test-integration-batched.sh - Use dynamic process.cwd() instead of hardcoded path in jest.config.js - Enhance quality-gate.ts to parse test logs when results file missing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: Complete Agentic QE Fleet v2.1 implementation (closes #101) ## Implemented Features ### Error Recovery Enhancement (Task 1.3) - CircuitBreaker class with state management (CLOSED/OPEN/HALF_OPEN) - RetryStrategy with exponential/linear/constant backoff - RecoveryOrchestrator with 6 recovery strategies - Transport fallback mechanisms ### Dynamic Skill Loader (Task 2.2) - Metadata-only initial loading (98% token reduction) - On-demand full skill retrieval - LRU caching with configurable TTL (30min default) - Preload suggestions for critical workflows ### Swarm Learning Optimizer (Task 4.1) - Topology recommendation engine (hierarchical/mesh/ring/star) - Agent allocation with capability matching and load balancing - Bottleneck detection (agent/memory/coordination/IO) - Real-time performance adjustments - Added getLatestRecommendation() method ### Workflow Orchestrator (Task 4.2) - AdaptiveScheduler with dynamic strategy selection - Priority-based task queue with age boosting - Task dependency resolution - Work stealing and backpressure handling - Added getQueueDepth() and getStatus() methods ### Unified Memory Coordinator (Task 4.3) - Consolidated memory managers (SQLite, AgentDB, Vector, JSON) - Automatic failover chain with health monitoring - Batch operations and namespace isolation - Periodic sync between backends ### SwarmCoordinator Improvements - Real CPU utilization tracking via process.cpuUsage() - Queue depth from WorkflowOrchestrator - Optimizer recommendations in feedback data - Calculated average complexity from metrics ## Additional Changes - Migration documentation and test restructuring plan - GitHub issue templates and workflows - Test suite improvements and cleanup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: optimize 38 QE skills with agent-focused format (#102) - Add enhanced YAML frontmatter (tokenEstimate, agents, tags, etc.) - Add <default_to_action> blocks for immediate actionable guidance - Add Quick Reference Cards with tables for at-a-glance info - Add Agent Integration examples using Task() pattern - Add Agent Coordination Hints (memory namespace + fleet coordination) - Condense content optimized for agent consumption - Reduce total token footprint by ~65% across skills Skills updated: - Core QE: agentic-quality-engineering, holistic-testing-pact - Testing Types: api-testing, chaos-engineering, compatibility, compliance, contract, database, exploratory, localization, mobile, mutation, performance, regression, security, visual-testing - Methodologies: tdd-london-chicago, xp-practices, context-driven, risk-based, shift-left, shift-right - Analysis: code-review-quality, quality-metrics, test-design-techniques - Strategy: test-automation-strategy, test-data-management, test-environment-management, test-reporting-analytics - CI/CD: cicd-pipeline-qe-orchestrator, accessibility-testing - Communication: brutal-honesty-review, bug-reporting-excellence, consultancy-practices, sherlock-review, six-thinking-hats, technical-writing - Refactoring: refactoring-patterns Also includes: package.json updates, docs/optimization/, docs/templates/, scripts/validate-skill-optimization.ts Skipped: testability-scoring (pending PR from @fndlalit) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * release: v2.1.0 - Comprehensive QX Analysis & Skills Optimization ## Summary - Comprehensive QX Analysis with 23+ heuristics (PR #104 by @fndlalit) - 38 QE Skills optimized with agent-focused format (PR #102) - Testability Scoring skill v2.1 with optimized format - QX Partner Agent v2.1 with enhanced capabilities - Fix MCP SDK compatibility for @modelcontextprotocol/sdk bump (PR #105) ## Changes - .claude/agents/qx-partner.md: Updated to v2.1 with domain-specific detection - .claude/skills/testability-scoring/SKILL.md: Optimized format (59% token reduction) - src/mcp/server.ts: Removed deprecated 'description' field for MCP SDK compatibility - package.json: Bumped version to 2.1.0 - README.md: Updated version and release notes - CHANGELOG.md: Added v2.1.0 release notes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1540 lines
40 KiB
TypeScript
1540 lines
40 KiB
TypeScript
/**
|
|
* TestGeneratorAgent - Null Safety & Edge Case Test Suite
|
|
*
|
|
* CRITICAL PRIORITY: Focus on null pointer risks in lines 30-180
|
|
* Target: 80% line coverage, 75% branch coverage
|
|
*
|
|
* Test Coverage:
|
|
* 1. Null/undefined input handling (PRIORITY)
|
|
* 2. Boundary conditions
|
|
* 3. Error scenarios
|
|
* 4. Edge cases
|
|
* 5. Configuration validation
|
|
*/
|
|
|
|
import { TestGeneratorAgent, TestGeneratorConfig, TestGenerationRequest, TestGenerationResult } from '../../../src/agents/TestGeneratorAgent';
|
|
import { SwarmMemoryManager } from '../../../src/core/memory/SwarmMemoryManager';
|
|
import { EventEmitter } from 'events';
|
|
import { QEAgentType, AgentContext, TestType, QETask, TaskAssignment, AgentCapability } from '../../../src/types';
|
|
|
|
describe('TestGeneratorAgent - Null Safety & Edge Cases', () => {
|
|
let memoryStore: SwarmMemoryManager;
|
|
let eventBus: EventEmitter;
|
|
|
|
beforeEach(async () => {
|
|
memoryStore = new SwarmMemoryManager(':memory:');
|
|
await memoryStore.initialize();
|
|
eventBus = new EventEmitter();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (memoryStore) {
|
|
await memoryStore.close();
|
|
}
|
|
});
|
|
|
|
describe('Constructor - Null/Undefined Handling', () => {
|
|
it('should handle undefined enablePatterns gracefully (defaults to true)', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: undefined // Explicitly undefined
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle undefined enableLearning gracefully (defaults to true)', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enableLearning: undefined // Explicitly undefined
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle undefined minPatternConfidence (defaults to 0.85)', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
minPatternConfidence: undefined // Explicitly undefined
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle undefined patternMatchTimeout (defaults to 50ms)', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
patternMatchTimeout: undefined // Explicitly undefined
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle null context gracefully', () => {
|
|
// Agent should be resilient and not throw on null context
|
|
// It provides defaults internally for graceful degradation
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context: null as any, // Null context - agent handles gracefully
|
|
memoryStore,
|
|
eventBus
|
|
});
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle undefined context gracefully', () => {
|
|
// Agent should be resilient and not throw on undefined context
|
|
// It provides defaults internally for graceful degradation
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context: undefined as any, // Undefined context - agent handles gracefully
|
|
memoryStore,
|
|
eventBus
|
|
});
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle null memoryStore', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
expect(() => {
|
|
new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore: null as any, // Null memoryStore
|
|
eventBus
|
|
});
|
|
}).toThrow();
|
|
});
|
|
|
|
it('should handle null eventBus', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
expect(() => {
|
|
new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus: null as any // Null eventBus
|
|
});
|
|
}).toThrow();
|
|
});
|
|
});
|
|
|
|
describe('Configuration Boundary Conditions', () => {
|
|
it('should handle minPatternConfidence = 0 (minimum boundary)', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
minPatternConfidence: 0 // Minimum boundary
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle minPatternConfidence = 1 (maximum boundary)', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
minPatternConfidence: 1 // Maximum boundary
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle negative minPatternConfidence', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
minPatternConfidence: -0.5 // Invalid negative value
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle minPatternConfidence > 1', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
minPatternConfidence: 1.5 // Invalid > 1 value
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle patternMatchTimeout = 0 (zero timeout)', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
patternMatchTimeout: 0 // Zero timeout
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle very large patternMatchTimeout', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
patternMatchTimeout: Number.MAX_SAFE_INTEGER // Very large timeout
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
|
|
it('should handle negative patternMatchTimeout', () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true,
|
|
patternMatchTimeout: -100 // Negative timeout
|
|
});
|
|
|
|
expect(agent).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Test Generation Request - Null/Undefined Fields', () => {
|
|
let agent: TestGeneratorAgent;
|
|
|
|
beforeEach(async () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: false,
|
|
enableLearning: false
|
|
});
|
|
|
|
await agent.initialize();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (agent) {
|
|
await agent.terminate();
|
|
}
|
|
});
|
|
|
|
it('should handle null sourceCode.ast', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: null as any, // Null AST
|
|
files: [
|
|
{
|
|
path: '/test/src/Test.ts',
|
|
content: 'export function test() { return true; }',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-null-ast',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-null-ast',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle empty files array', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [], // Empty files array
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 0,
|
|
cognitiveComplexity: 0,
|
|
functionCount: 0,
|
|
linesOfCode: 0
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-empty-files',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-empty-files',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] Source code files are required but missing'
|
|
);
|
|
});
|
|
|
|
it('should handle null file content', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/NullContent.ts',
|
|
content: null as any, // Null content
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 0,
|
|
linesOfCode: 0
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-null-content',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-null-content',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle undefined file path', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: undefined as any, // Undefined path
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-undefined-path',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-undefined-path',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle null complexityMetrics', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Test.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: null as any // Null metrics
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-null-metrics',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-null-metrics',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] Source code complexity metrics are required'
|
|
);
|
|
});
|
|
|
|
it('should handle zero complexity metrics', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Zero.ts',
|
|
content: '// Empty file',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 0, // Zero complexity
|
|
cognitiveComplexity: 0,
|
|
functionCount: 0,
|
|
linesOfCode: 0
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-zero-complexity',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-zero-complexity',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle negative complexity metrics', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Negative.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: -5, // Negative (invalid)
|
|
cognitiveComplexity: -3,
|
|
functionCount: -1,
|
|
linesOfCode: -10
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-negative-complexity',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-negative-complexity',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Constraints - Boundary Conditions', () => {
|
|
let agent: TestGeneratorAgent;
|
|
|
|
beforeEach(async () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: false,
|
|
enableLearning: false
|
|
});
|
|
|
|
await agent.initialize();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (agent) {
|
|
await agent.terminate();
|
|
}
|
|
});
|
|
|
|
it('should handle maxTests = 0', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Zero.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 0, // Zero max tests
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-max-zero',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-max-zero',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] constraints.maxTests must be a positive number'
|
|
);
|
|
});
|
|
|
|
it('should handle very large maxTests', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Large.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: Number.MAX_SAFE_INTEGER, // Very large
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-max-large',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-max-large',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle negative maxTests', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Negative.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: -100, // Negative (invalid)
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-max-negative',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-max-negative',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] constraints.maxTests must be a positive number'
|
|
);
|
|
});
|
|
|
|
it('should handle empty testTypes array', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Empty.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [] // Empty array
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-empty-types',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-empty-types',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] constraints.testTypes must be a non-empty array'
|
|
);
|
|
});
|
|
|
|
it('should handle maxExecutionTime = 0', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/ZeroTime.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 0, // Zero timeout
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-zero-time',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-zero-time',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] constraints.maxExecutionTime must be a positive number'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('Coverage Target - Boundary Conditions', () => {
|
|
let agent: TestGeneratorAgent;
|
|
|
|
beforeEach(async () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: false,
|
|
enableLearning: false
|
|
});
|
|
|
|
await agent.initialize();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (agent) {
|
|
await agent.terminate();
|
|
}
|
|
});
|
|
|
|
it('should handle coverage target = 0%', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Zero.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 0, // 0% coverage
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-coverage-zero',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-coverage-zero',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle coverage target = 100%', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Full.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 100, // 100% coverage
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-coverage-full',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-coverage-full',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle coverage target > 100%', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Over.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 150, // > 100% (invalid)
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-coverage-over',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-coverage-over',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] Coverage target must be a number between 0-100'
|
|
);
|
|
});
|
|
|
|
it('should handle negative coverage target', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Negative.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: -50, // Negative (invalid)
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-coverage-negative',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-coverage-negative',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow(
|
|
'[TestGeneratorAgent] Coverage target must be a number between 0-100'
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('Error Scenarios', () => {
|
|
let agent: TestGeneratorAgent;
|
|
|
|
beforeEach(async () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: false,
|
|
enableLearning: false
|
|
});
|
|
|
|
await agent.initialize();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (agent) {
|
|
await agent.terminate();
|
|
}
|
|
});
|
|
|
|
it('should handle malformed task with null requirements', async () => {
|
|
const task: QETask = {
|
|
id: 'test-null-req',
|
|
type: 'test-generation',
|
|
requirements: null as any, // Null requirements
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-null-req',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow();
|
|
});
|
|
|
|
it('should handle malformed task with undefined requirements', async () => {
|
|
const task: QETask = {
|
|
id: 'test-undef-req',
|
|
type: 'test-generation',
|
|
requirements: undefined as any, // Undefined requirements
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-undef-req',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
await expect(agent.executeTask(assignment)).rejects.toThrow();
|
|
});
|
|
|
|
it('should handle invalid framework name', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Invalid.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'invalid-framework-xyz' as any, // Invalid framework
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-invalid-framework',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-invalid-framework',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
// Should still generate tests, but may default to jest
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('should handle unsupported language', async () => {
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Unsupported.xyz',
|
|
content: 'UNSUPPORTED LANGUAGE CODE',
|
|
language: 'xyz-lang' // Unsupported language
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-unsupported-lang',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-unsupported-lang',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
// Should still attempt generation
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Memory Operations - Null Safety', () => {
|
|
let agent: TestGeneratorAgent;
|
|
|
|
beforeEach(async () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: false,
|
|
enableLearning: false
|
|
});
|
|
|
|
await agent.initialize();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (agent) {
|
|
await agent.terminate();
|
|
}
|
|
});
|
|
|
|
it('should handle memory store operations with null values', async () => {
|
|
// This tests the agent's internal memory handling
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Memory.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-memory-null',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-memory-null',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
|
|
// Verify memory was stored
|
|
const agentId = agent.getStatus().agentId.id;
|
|
const stored = await memoryStore.retrieve(`agent:${agentId}:last-generation`);
|
|
expect(stored).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Pattern-Based Generation - Null Safety', () => {
|
|
it('should handle pattern generation with null applicable patterns', async () => {
|
|
const context: AgentContext = {
|
|
workspaceRoot: '/test',
|
|
config: { timeout: 30000, retries: 3, logLevel: 'info' }
|
|
};
|
|
|
|
const agent = new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context,
|
|
memoryStore,
|
|
eventBus,
|
|
enablePatterns: true, // Enable patterns
|
|
enableLearning: false
|
|
});
|
|
|
|
await agent.initialize();
|
|
|
|
const request: TestGenerationRequest = {
|
|
sourceCode: {
|
|
ast: {},
|
|
files: [
|
|
{
|
|
path: '/test/src/Pattern.ts',
|
|
content: 'export function test() {}',
|
|
language: 'typescript'
|
|
}
|
|
],
|
|
complexityMetrics: {
|
|
cyclomaticComplexity: 1,
|
|
cognitiveComplexity: 1,
|
|
functionCount: 1,
|
|
linesOfCode: 1
|
|
}
|
|
},
|
|
framework: 'jest',
|
|
coverage: {
|
|
target: 80,
|
|
type: 'line'
|
|
},
|
|
constraints: {
|
|
maxTests: 50,
|
|
maxExecutionTime: 30000,
|
|
testTypes: [TestType.UNIT]
|
|
}
|
|
};
|
|
|
|
const task: QETask = {
|
|
id: 'test-pattern-null',
|
|
type: 'test-generation',
|
|
payload: request,
|
|
status: 'pending',
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-pattern-null',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment) as TestGenerationResult;
|
|
expect(result).toBeDefined();
|
|
expect(result.patterns).toBeDefined();
|
|
expect(result.generationMetrics.patternsUsed).toBeDefined();
|
|
|
|
await agent.terminate();
|
|
});
|
|
});
|
|
});
|