Testing Guidelines - robwhite4/claude-memory GitHub Wiki
Testing Guidelines
This guide covers testing practices for Claude Memory development.
Test Structure
Claude Memory uses Jest for testing with the following structure:
test/
├── basic.test.js # Core functionality tests
├── enhanced.test.js # v1.2+ feature tests
├── edge-cases.test.js # Error handling tests
├── global-flags.test.js # CLI flag tests
├── multi-context.test.js # Context system tests
└── fixtures/ # Test data and mocks
Running Tests
Basic Commands
# Run all tests
npm test
# Run specific test suite
npm run test:basic
npm run test:enhanced
# Run with coverage
npm run test:coverage
# Run in watch mode
npm run test:watch
# Run linting
npm run lint
npm run lint:fix
Test Suites
-
Basic Tests - Core functionality
- Session management
- Task operations
- Pattern tracking
- Decision recording
-
Enhanced Tests - Advanced features
- Knowledge management
- Import/export
- Multi-file context
- Token optimization
-
Edge Case Tests - Error handling
- Invalid inputs
- File system errors
- Corruption recovery
- Permission issues
-
Global Flag Tests - CLI behavior
- --dry-run functionality
- --force operations
- --debug output
- --config handling
Writing Tests
Test Structure
describe('Feature Name', () => {
let memory;
beforeEach(() => {
// Setup test instance
memory = new ClaudeMemory(testDir);
});
afterEach(() => {
// Cleanup
if (fs.existsSync(testDir)) {
fs.rmSync(testDir, { recursive: true });
}
});
test('should perform expected behavior', () => {
// Arrange
const input = 'test data';
// Act
const result = memory.someMethod(input);
// Assert
expect(result).toBe(expectedValue);
});
});
Testing Best Practices
- Isolation: Each test should be independent
- Clarity: Test names should describe what they test
- Coverage: Aim for >90% code coverage
- Edge Cases: Test error conditions and boundaries
- Mocking: Mock file system operations when appropriate
Common Test Patterns
Testing CLI Commands
test('should add task with dry-run', () => {
const result = memory.addTask('Test task', 'high', null, true);
expect(result.dryRun).toBe(true);
expect(result.wouldCreate).toBeTruthy();
expect(memory.getTasks()).toHaveLength(0); // Not actually added
});
Testing File Operations
test('should handle missing directory', () => {
const badPath = '/nonexistent/path';
expect(() => {
new ClaudeMemory(badPath);
}).toThrow('Cannot create directory');
});
Testing Error Handling
test('should validate task priority', () => {
expect(() => {
memory.addTask('Task', 'invalid-priority');
}).toThrow('Invalid priority');
});
Coverage Requirements
Maintain high test coverage:
- Statements: >90%
- Branches: >85%
- Functions: >90%
- Lines: >90%
Check coverage with:
npm run test:coverage
open coverage/lcov-report/index.html
CI/CD Integration
Tests run automatically on:
- Pull requests
- Commits to main/develop
- Release workflows
GitHub Actions Workflow
- name: Run tests
run: |
npm ci
npm run lint
npm test
npm run test:coverage
Testing Checklist
Before submitting a PR:
- All tests pass (
npm test
) - No linting errors (
npm run lint
) - Coverage maintained/improved
- New features have tests
- Edge cases considered
- Tests run in isolation
- CI checks pass
Debugging Tests
Run Single Test
# Run specific test file
npm test -- basic.test.js
# Run specific test case
npm test -- --testNamePattern="should add task"
Debug Mode
# Run with Node debugger
node --inspect-brk node_modules/.bin/jest
# Use console.log in tests
test('debug example', () => {
console.log('Debug info:', variable);
// ...
});
Common Issues
-
Timeout Errors
test('async operation', async () => { // Increase timeout for slow operations jest.setTimeout(10000); await someSlowOperation(); }, 10000);
-
File System Conflicts
// Use unique test directories const testDir = path.join(os.tmpdir(), `claude-test-${Date.now()}`);
-
Mock Issues
// Clear mocks between tests afterEach(() => { jest.clearAllMocks(); });
Performance Testing
For performance-critical code:
test('should handle large datasets', () => {
const start = Date.now();
// Add 1000 tasks
for (let i = 0; i < 1000; i++) {
memory.addTask(`Task ${i}`);
}
const duration = Date.now() - start;
expect(duration).toBeLessThan(1000); // Should complete in 1s
});
Test Data
Use realistic test data:
- Real-world task descriptions
- Actual error scenarios
- Production-like file sizes
- Various character encodings
Contributing Tests
When adding new features:
- Write tests first (TDD)
- Cover happy path
- Cover error cases
- Update existing tests if needed
- Document test purpose
See also:
- Development-Workflow - Development process
- Contributing-Guidelines - Contribution guidelines
- Release-Process - Release testing requirements