mirror of
https://github.com/proffesor-for-testing/agentic-qe.git
synced 2026-09-19 08:45:47 +08:00
2b71ae4eb8
## 🔒 Security Fixes ### eval() Removal - Critical Security Vulnerability Fixed - **File**: `src/agents/TestDataArchitectAgent.ts` - **Impact**: Eliminated arbitrary code execution risk - **Solution**: Implemented safe expression evaluator with parser-based approach - **Supports**: - Comparison operators: `===`, `!==`, `==`, `!=`, `>`, `<`, `>=`, `<=` - Logical operators: `&&`, `||` - Boolean values: `true`, `false` - Number and string comparisons - **Lines**: 102 lines added (safeEvaluateExpression + parseValue methods) ## ✨ UX Enhancements ### CLAUDE.md Append Strategy - User-Requested Feature - **File**: `src/cli/commands/init.ts` - **User Feedback**: "AQE instructions should append by default, not prepend" - **Interactive Mode**: Prompts user to choose prepend or append - **--yes Mode**: Defaults to append (less disruptive to existing configs) - **Features**: - Auto-backup existing CLAUDE.md to CLAUDE.md.backup - Clear visual separator (---) between sections - User confirmation messages - **Lines**: 49 lines modified ### CLI Skills Count Fix - Accurate Display - **File**: `src/cli/commands/skills/index.ts` - **Before**: Showed "8/17" (hardcoded, incorrect) - **After**: Shows "34/34" (dynamic, accurate) - **Solution**: Added `getTotalQESkillsCount()` method using `QE_SKILLS.flatMap()` - **Future-proof**: Auto-updates when skills added - **Lines**: 11 lines modified ## 🎓 New Agent - Cherry-Picked from PR #22 ### CodeComplexityAnalyzerAgent Integration - **Author**: @mondweep (PR #22) - **Purpose**: Educational code complexity analysis and refactoring recommendations - **Files**: 7 files, 2,758 lines of code - **Capabilities**: - Cyclomatic complexity calculation - Cognitive complexity analysis - AI-powered refactoring suggestions - Quality scoring (0-100 scale) - Memory integration (`aqe/complexity/*`) - **Test Coverage**: 529 lines, 13+ test scenarios - **Documentation**: 754 lines (README + Claude agent definition) - **Examples**: 871 lines (3 interactive examples) ## 🔧 Code Quality Improvements ### Agent Enhancements - **BaseAgent.ts**: 136 lines modified - Improved property access patterns - Better encapsulation with public accessors - Enhanced lifecycle management - **TestGeneratorAgent.ts**: 377 lines added - Comprehensive null safety improvements - Enhanced error handling - Better context validation - **QualityGateAgent.ts**: 64 lines modified - Improved context handling - Better validation logic ### MCP Handler Improvements - **test-generate.ts**: 33 lines modified (better parameter handling) - **quality-analyze.ts**: 28 lines modified (context fix) - **regression-risk-analyze.ts**: 85 lines modified (parameter aliasing fix) ### Infrastructure Additions - **AgentLifecycleManager.ts**: 274 new lines (lifecycle coordination) - **SwarmMemoryManager.ts**: 3 lines modified (improved coordination) - **AgentRegistry.ts**: 20 lines added (better agent registration) ## 🧪 Testing Enhancements ### New Integration Tests (5 Test Suites) - **fleet-management.integration.test.ts**: 491 lines - **parameter-validation.integration.test.ts**: 606 lines - **quality-analyze.integration.test.ts**: 393 lines - **regression-risk.integration.test.ts**: 505 lines - **test-execution.integration.test.ts**: 536 lines - **test-harness.ts**: 289 lines (shared test utilities) - **Total**: 2,820 lines of integration test coverage ### Enhanced Unit Tests - **BaseAgent.enhanced.test.ts**: 909 lines (comprehensive BaseAgent testing) - **TestGeneratorAgent.null-safety.test.ts**: 1,511 lines (null safety validation) - **Total**: 2,420 lines of new unit test coverage ### Test Improvements - **PredictionTools.test.ts**: 118 lines modified - **Agent.test.ts**: 11 lines modified ## 📚 Documentation Expansion (27,439 insertions) ### Release Documentation (7 documents) - **RELEASE-1.3.6-PREPARATION.md**: 443 lines (complete release checklist) - **SECURITY-SCAN-RELEASE-1.3.6.md**: 422 lines (security validation) - **THREE-ISSUE-FIXES-SUMMARY.md**: 196 lines (user-reported fixes) - **CHERRY-PICK-PR22-SUMMARY.md**: 412 lines (integration details) - **FINAL-STATUS-REPORT-2025-10-30.md**: 403 lines (status summary) - **FINAL-MCP-VERIFICATION-SUMMARY.md**: 338 lines (MCP validation) - **MCP-PRODUCTION-READINESS-REPORT.md**: 318 lines (production readiness) ### Technical Documentation (7 documents) - **MCP-TOOLS-REFERENCE.md**: 1,555 lines (complete MCP API reference) - **MCP-TOOLS-USER-GUIDE.md**: 626 lines (user guide) - **MCP-TOOLS-AUTO-GENERATED.md**: 934 lines (auto-generated docs) - **MCP-TOOLS-MIGRATION.md**: 437 lines (migration guide) - **complexity-mitigation-plan.md**: 537 lines (code quality roadmap) - **swarm-execution-report.md**: 985 lines (execution analysis) - **HONEST-IMPLEMENTATION-ANALYSIS.md**: 62 lines (transparency report) ### Fix Documentation (7 documents) - **MCP-TOOLS-COMPLETE-FIX-REPORT.md**: 619 lines (comprehensive fix report) - **three-issue-fixes.md**: 345 lines (user-reported fixes) - **quality-analyze-context-fix.md**: 195 lines - **regression-risk-parameter-aliasing.md**: 303 lines - **test-generator-agent-null-safety-fixes.md**: 422 lines - **typescript-compilation-errors-fixed-2025-10-30.md**: 273 lines - **MCP-TOOLS-FIX-SUMMARY.md**: 272 lines ### Refactoring Plans (4 documents) - **swarm-memory-manager-refactoring-plan.md**: 796 lines - **base-agent-refactoring-plan.md**: 658 lines - **refactoring-summary.md**: 404 lines - **REFACTORING_STATUS.md**: 210 lines ### Testing Documentation (6 documents) - **mcp-tools-test-report.md**: 1,260 lines (comprehensive test report) - **testing-workflow.md**: 691 lines (MCP testing guide) - **TestGeneratorAgent-test-plan.md**: 318 lines (test plan) - **coverage-analysis-2025-10-30.md**: 661 lines (coverage report) - **regression-validation-report-2025-10-30.md**: 450 lines (regression validation) - **README.md** (tests/integration/mcp): 277 lines (integration test guide) ### CI/CD Documentation (3 documents) - **mcp-cicd-pipeline.md**: 402 lines (pipeline architecture) - **mcp-pipeline-setup-summary.md**: 343 lines (setup guide) - **mcp-cicd-implementation-notes.md**: 280 lines (implementation notes) ### MCP Verification (2 documents) - **MCP-VERIFICATION-SUMMARY.md**: 286 lines - **PR-22-ANALYSIS.md**: 373 lines ### Coverage Analysis (2 documents) - **coverage-analysis-2025-10-30.md**: 661 lines - **coverage-analysis-summary.json**: 417 lines (structured data) ## 🛠️ Scripts & Automation (5 Scripts, 2,117 Lines) ### New Utility Scripts - **validate-mcp-tools.js**: 280 lines (MCP tool validation) - **generate-mcp-report.js**: 252 lines (report generation) - **generate-mcp-docs.js**: 270 lines (documentation generation) - **verify-mcp-production-readiness.js**: 564 lines (production checks) - **test-issue-fixes.js**: 224 lines (fix verification) - **mcp-tools-summary.json**: 344 lines (structured summary) ## 📊 Examples & Guides ### MCP Integration Examples (2 Examples) - **basic-test-generation.js**: 200 lines (starter example) - **quality-analysis-pipeline.js**: 360 lines (advanced workflow) ## ⚙️ CI/CD Enhancements ### GitHub Actions Workflow - **.github/workflows/mcp-tools-test.yml**: 197 lines - Automated MCP tool testing - Multi-environment validation - Production readiness checks ### Git Hooks - **.husky/pre-commit**: 14 lines (pre-commit validation) ## 📦 Configuration Updates ### Version & Dependencies - **package.json**: Version bumped to 1.3.6 - **package-lock.json**: Dependency lock updated - **README.md**: Version references updated (27 lines modified) - **.claude/settings.json**: 4 lines modified ### CHANGELOG - **CHANGELOG.md**: 37 lines added - Complete v1.3.6 changelog entry - Security fixes documented - UX enhancements documented - Testing improvements documented ## 📈 Statistics Summary ### Code Changes - **78 files changed** - **27,439 insertions** (+) - **181 deletions** (-) - **Net change**: +27,258 lines ### Breakdown by Category - **Source Code**: ~1,200 lines (agents, handlers, infrastructure) - **Tests**: ~5,240 lines (integration + unit tests) - **Documentation**: ~18,000 lines (guides, reports, plans) - **Scripts**: ~2,117 lines (automation utilities) - **Examples**: ~560 lines (MCP examples) - **CI/CD**: ~211 lines (workflows + hooks) ### Quality Metrics - ✅ **TypeScript Compilation**: 0 errors (16 errors fixed) - ✅ **Security Vulnerabilities**: 0 critical (1 fixed) - ✅ **Integration Tests**: 5 new test suites, 2,820 lines - ✅ **Unit Tests**: 2,420 new lines - ✅ **Documentation**: 100% comprehensive coverage - ✅ **Backward Compatibility**: 100% maintained ## 🎯 User Impact ### Immediate Benefits 1. **Security**: Eliminates arbitrary code execution vulnerability 2. **UX**: Less disruptive CLAUDE.md initialization 3. **Accuracy**: Correct skills count display (34/34) 4. **Quality**: CodeComplexityAnalyzerAgent for refactoring guidance 5. **Reliability**: 16 TypeScript errors resolved ### Developer Experience 1. **Better Documentation**: 18,000+ lines of guides and references 2. **Better Testing**: 5,240 new lines of test coverage 3. **Better Tooling**: 2,117 lines of automation scripts 4. **Better Examples**: MCP integration examples 5. **Better CI/CD**: Automated testing and validation ## 🔄 Migration & Compatibility ### Breaking Changes - **NONE** - Fully backward compatible ### Deprecations - **NONE** ### New Features (Opt-in) - CodeComplexityAnalyzerAgent (available via Claude Code or MCP) - Interactive CLAUDE.md placement (interactive mode only) ## ✅ Verification ### Pre-Release Checks - ✅ TypeScript compilation: 0 errors - ✅ All three user-reported fixes verified - ✅ Integration tests passing - ✅ Documentation complete - ✅ CHANGELOG updated - ✅ Version numbers updated (package.json, README.md) - ✅ Security scan: No vulnerabilities - ✅ Backward compatibility verified ### Production Readiness - ✅ MCP tools validated (54 tools) - ✅ Agent registry verified (17 agents) - ✅ Skills library verified (34 skills) - ✅ CI/CD pipeline configured - ✅ Pre-commit hooks installed ## 🙏 Acknowledgments - **@mondweep**: CodeComplexityAnalyzerAgent contribution (PR #22) - **User Feedback**: CLAUDE.md append strategy request - **User Feedback**: CLI skills count display bug report - **User Feedback**: eval() security concern ## 📝 Release Notes **Version**: 1.3.6 **Date**: 2025-10-30 **Type**: Security & Quality Patch Release **Status**: Production Ready **Upgrade Recommendation**: 🔴 **HIGH PRIORITY** - Security vulnerability fixed (eval() removal) - User experience improvements - Enhanced stability (16 TypeScript errors fixed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1512 lines
39 KiB
TypeScript
1512 lines
39 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', () => {
|
|
expect(() => {
|
|
new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context: null as any, // Null context
|
|
memoryStore,
|
|
eventBus
|
|
});
|
|
}).toThrow();
|
|
});
|
|
|
|
it('should handle undefined context gracefully', () => {
|
|
expect(() => {
|
|
new TestGeneratorAgent({
|
|
type: QEAgentType.TEST_GENERATOR,
|
|
capabilities: [],
|
|
context: undefined as any, // Undefined context
|
|
memoryStore,
|
|
eventBus
|
|
});
|
|
}).toThrow();
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-empty-files',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-null-metrics',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-max-zero',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment) as TestGenerationResult;
|
|
expect(result).toBeDefined();
|
|
// With maxTests = 0, should generate 0 tests
|
|
expect(result.generationMetrics.testsGenerated).toBe(0);
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-max-negative',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-empty-types',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-zero-time',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-coverage-over',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
priority: 'medium',
|
|
createdAt: new Date()
|
|
};
|
|
|
|
const assignment: TaskAssignment = {
|
|
id: 'assignment-coverage-negative',
|
|
task,
|
|
agentId: agent.getStatus().agentId.id,
|
|
assignedAt: new Date(),
|
|
status: 'assigned'
|
|
};
|
|
|
|
const result = await agent.executeTask(assignment);
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
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',
|
|
requirements: request,
|
|
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();
|
|
});
|
|
});
|
|
});
|