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

  1. Basic Tests - Core functionality

    • Session management
    • Task operations
    • Pattern tracking
    • Decision recording
  2. Enhanced Tests - Advanced features

    • Knowledge management
    • Import/export
    • Multi-file context
    • Token optimization
  3. Edge Case Tests - Error handling

    • Invalid inputs
    • File system errors
    • Corruption recovery
    • Permission issues
  4. 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

  1. Isolation: Each test should be independent
  2. Clarity: Test names should describe what they test
  3. Coverage: Aim for >90% code coverage
  4. Edge Cases: Test error conditions and boundaries
  5. 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

  1. Timeout Errors

    test('async operation', async () => {
      // Increase timeout for slow operations
      jest.setTimeout(10000);
      await someSlowOperation();
    }, 10000);
    
  2. File System Conflicts

    // Use unique test directories
    const testDir = path.join(os.tmpdir(), `claude-test-${Date.now()}`);
    
  3. 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:

  1. Write tests first (TDD)
  2. Cover happy path
  3. Cover error cases
  4. Update existing tests if needed
  5. Document test purpose

See also: