mnemos-coder
Version:
CLI-based coding agent with graph-based execution loop and terminal UI
181 lines (162 loc) • 5.28 kB
JavaScript
/**
* Test-First Verification System
* Based on qwen-code's emphasis on self-verification through tests
* Ensures code changes are validated before completion
*/
export class TestFirstVerification {
/**
* Determine verification strategy based on project type
*/
static async determineStrategy(projectRoot) {
const strategy = {
writeTestsFirst: false,
runExistingTests: true,
useDebugStatements: false,
verificationCommands: []
};
// Check for test frameworks and commands
const patterns = {
node: {
files: ['package.json'],
testCommands: ['npm test', 'npm run test', 'yarn test'],
lintCommands: ['npm run lint', 'yarn lint'],
typeCommands: ['npm run typecheck', 'tsc --noEmit']
},
python: {
files: ['requirements.txt', 'setup.py', 'pyproject.toml'],
testCommands: ['pytest', 'python -m pytest', 'python -m unittest'],
lintCommands: ['ruff check', 'flake8', 'pylint'],
typeCommands: ['mypy']
},
rust: {
files: ['Cargo.toml'],
testCommands: ['cargo test'],
lintCommands: ['cargo clippy'],
typeCommands: ['cargo check']
},
go: {
files: ['go.mod'],
testCommands: ['go test ./...'],
lintCommands: ['golangci-lint run'],
typeCommands: ['go build']
}
};
// Detect project type and add appropriate commands
for (const [lang, config] of Object.entries(patterns)) {
const hasProjectFile = await this.checkFilesExist(projectRoot, config.files);
if (hasProjectFile) {
strategy.verificationCommands.push(...config.testCommands);
strategy.verificationCommands.push(...config.lintCommands);
strategy.verificationCommands.push(...config.typeCommands);
break;
}
}
return strategy;
}
/**
* Generate test template based on the code being modified
*/
static generateTestTemplate(functionName, language, testFramework) {
const templates = {
javascript: (fn) => `
describe('${fn}', () => {
it('should handle normal cases', () => {
// Arrange
const input = {};
// Act
const result = ${fn}(input);
// Assert
expect(result).toBeDefined();
});
it('should handle edge cases', () => {
// Test null/undefined inputs
expect(() => ${fn}(null)).not.toThrow();
});
it('should handle error cases', () => {
// Test invalid inputs
const invalidInput = {};
expect(() => ${fn}(invalidInput)).toThrow();
});
});`,
python: (fn) => `
import pytest
from module import ${fn}
class Test${fn.charAt(0).toUpperCase() + fn.slice(1)}:
def test_normal_case(self):
"""Test normal operation"""
# Arrange
input_data = {}
# Act
result = ${fn}(input_data)
# Assert
assert result is not None
def test_edge_case(self):
"""Test edge cases"""
# Test with None
with pytest.raises(TypeError):
${fn}(None)
def test_error_case(self):
"""Test error handling"""
invalid_input = {}
with pytest.raises(ValueError):
${fn}(invalid_input)
`,
typescript: (fn) => `
describe('${fn}', () => {
it('should handle normal cases', () => {
// Arrange
const input = {} as InputType;
// Act
const result = ${fn}(input);
// Assert
expect(result).toBeDefined();
expect(result).toMatchObject({});
});
it('should handle edge cases', () => {
// Test null/undefined inputs
expect(() => ${fn}(null as any)).not.toThrow();
});
it('should handle error cases', () => {
// Test invalid inputs
const invalidInput = {} as InputType;
expect(() => ${fn}(invalidInput)).toThrow(Error);
});
});`
};
return templates[language]?.(functionName) || '// Test template not available for this language';
}
/**
* Create verification loop for code changes
*/
static createVerificationLoop() {
return `
## Verification Loop Process
1. **Write Test First**
- Define expected behavior
- Create test cases for success, edge, and error cases
2. **Implement Solution**
- Write minimal code to pass tests
- Focus on correctness first
3. **Run Tests**
- Execute test suite
- Verify all tests pass
4. **Add Debug Output**
- Insert console.log/print statements
- Verify logic flow
5. **Run Linting & Type Checking**
- Execute project linters
- Run type checkers
- Fix any issues
6. **Clean Up**
- Remove debug statements
- Refactor if needed
- Ensure tests still pass
`;
}
static async checkFilesExist(projectRoot, files) {
// This would use fs.existsSync in real implementation
// Simplified for demonstration
return true;
}
}
//# sourceMappingURL=TestFirstVerification.js.map