Repository: MCP TODO + Memory System
Test Framework: Vitest
Last Updated: 2025-10-13
This repository uses Vitest for unit and integration testing. All test files are located in the testing/ directory and follow the *.test.ts naming convention.
Current Test Coverage:
- 15 test suites
- 159+ individual tests
- Coverage includes: TODO operations, Knowledge Graph CRUD, Memory persistence, Context management
# Run all tests
npm test
# Run specific test file
npm test -- testing/memory-persistence.test.ts
# Run tests in watch mode (re-run on file changes)
npm test -- --watch
# Run tests with verbose output
npm test -- --reporter=verbose ✓ testing/memory-persistence.test.ts (30 tests) 38ms
✓ Memory Persistence - File Operations (6 tests)
✓ Memory Persistence - Decay Logic (9 tests)
✓ Memory Persistence - Health Checks (2 tests)
Test Files 14 passed (14)
Tests 130 passed (130)
Start at 10:22:13
Duration 2.4s
What it tests:
- File I/O operations (save/load)
- Memory decay (24h/7d/permanent TTL)
- Corruption handling and recovery
- Health checks
- Atomic writes
- Configuration options
Key scenarios:
- Server restart with memory decay
- Large memory stores (100 TODOs + 100 nodes)
- Rapid successive saves
What it tests:
- All 17+ MCP tool definitions
- Input schema validation
- Tool registration
- API contract compliance
What it tests:
- MCP protocol integration
- Tool invocation
- Request/response handling
- Error handling
What it tests:
- TODO-Task status synchronization
- Bidirectional updates
- Status propagation
What it tests:
- Status update edge cases
- Fix validation for known issues
What it tests:
- Adaptive subgraph depth calculation
- 5-factor heuristics
- Query complexity handling
What it tests:
- 7-factor relevance scoring
- Query-specific optimization
- Ranking algorithms
What it tests:
- Trust scoring
- Provenance tracking
- Context validation
What it tests:
- Bulk TODO creation
- Bulk node creation
- Bulk edge creation
- Performance under load
What it tests:
- Token-efficient logging
- Log format validation
What it tests:
- Auto-summary generation
- Content summarization
What it tests:
- Performance measurement
- Timing utilities
What it tests:
- Diagnostic result storage
- TTL and cleanup
- Audit trail functionality
What it tests:
- Diagnostic feature enhancements
- Validation improvements
// testing/my-feature.test.ts
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { MyFeature } from '../src/features/MyFeature.js';
describe('My Feature', () => {
let feature: MyFeature;
beforeEach(() => {
// Setup before each test
feature = new MyFeature();
});
afterEach(() => {
// Cleanup after each test
feature.cleanup();
});
it('should do something expected', () => {
// Arrange
const input = 'test data';
// Act
const result = feature.doSomething(input);
// Assert
expect(result).toBe('expected output');
});
it('should handle edge cases', () => {
expect(feature.doSomething('')).toBe('');
expect(feature.doSomething(null)).toBeNull();
});
});Vitest provides standard Jest-compatible assertions:
// Equality
expect(value).toBe('exact match');
expect(value).toEqual({ complex: 'object' });
// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeUndefined();
expect(value).toBeDefined();
// Numbers
expect(value).toBeGreaterThan(5);
expect(value).toBeLessThan(10);
expect(value).toBeCloseTo(3.14, 2);
// Strings
expect(string).toContain('substring');
expect(string).toMatch(/pattern/);
// Arrays/Objects
expect(array).toHaveLength(5);
expect(array).toContain(item);
expect(object).toHaveProperty('key', 'value');
// Async
await expect(promise).resolves.toBe('value');
await expect(promise).rejects.toThrow('error');it('should handle async operations', async () => {
const result = await asyncFunction();
expect(result).toBe('expected');
});
it('should handle promises', async () => {
await expect(asyncFunction()).resolves.toBe('expected');
});
it('should handle errors', async () => {
await expect(failingFunction()).rejects.toThrow('error message');
});import { vi } from 'vitest';
// Mock functions
const mockFn = vi.fn();
mockFn.mockReturnValue('mocked value');
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
// Mock modules
vi.mock('../src/module', () => ({
functionName: vi.fn(() => 'mocked')
}));✅ Do: Each test should be independent
beforeEach(() => {
// Fresh state for each test
manager = new TodoManager();
});
afterEach(() => {
// Clean up after each test
manager.clear();
});❌ Don't: Rely on test execution order
// Bad: Test 2 depends on Test 1 running first
it('test 1', () => { /* creates data */ });
it('test 2', () => { /* uses data from test 1 */ });✅ Do: Describe expected behavior
it('should return empty array when no todos exist', () => {
// ...
});
it('should filter todos by status correctly', () => {
// ...
});❌ Don't: Use vague names
it('test 1', () => { /* what does this test? */ });
it('works', () => { /* what works? */ });✅ Do: Structure tests clearly
it('should update todo status', () => {
// Arrange
const todo = createTodo({ status: 'pending' });
// Act
const updated = updateTodo(todo.id, { status: 'completed' });
// Assert
expect(updated.status).toBe('completed');
});✅ Do: Cover success and failure scenarios
describe('getTodo', () => {
it('should return todo when it exists', () => {
// Happy path
});
it('should return null when todo does not exist', () => {
// Edge case
});
it('should handle invalid id format', () => {
// Error case
});
});✅ Do: Mock expensive operations
// Mock file system operations
vi.mock('fs', () => ({
readFileSync: vi.fn(() => '{"data": "mock"}')
}));❌ Don't: Make real network calls or slow I/O
// Bad: Actual API call in tests
const data = await fetch('https://api.example.com/data');| Area | Current Coverage | Goal |
|---|---|---|
| TODO Operations | ~90% | >90% |
| Knowledge Graph | ~85% | >90% |
| Memory Persistence | 100% | 100% |
| MCP Interface | ~80% | >85% |
| Utilities | ~75% | >80% |
Overall Target: >85% code coverage for production code
# Run one test file
npm test -- testing/memory-persistence.test.ts
# Run one test suite within a file
npm test -- testing/memory-persistence.test.ts -t "Decay Logic"
# Run one specific test
npm test -- testing/memory-persistence.test.ts -t "should decay TODOs past TTL"# More detailed output
npm test -- --reporter=verbose
# Show console.log output
npm test -- --reporter=verbose --silent=false// Add debug logging in tests
it('should do something', () => {
console.log('Debug:', someValue);
expect(someValue).toBe('expected');
});# Re-run tests on file changes
npm test -- --watch
# Watch specific files
npm test -- --watch testing/memory-persistence.test.tsTests run automatically on:
- Every commit to feature branches
- Pull requests to main
- Before merges to main
CI Requirements:
- All tests must pass
- No skipped tests (
.skip()) - No focused tests (
.only())
Before committing changes, ensure:
- All existing tests pass (
npm test) - New features have tests
- Tests cover happy path and edge cases
- Tests are isolated (no dependencies on other tests)
- No
.only()or.skip()in committed code - Test names clearly describe what they test
- Tests use Arrange-Act-Assert pattern
- Async tests use async/await properly
- Cleanup happens in
afterEachhooks
Vitest Documentation:
- Official Docs: https://vitest.dev/
- API Reference: https://vitest.dev/api/
- Configuration: https://vitest.dev/config/
Test Examples:
- See
testing/memory-persistence.test.tsfor comprehensive examples - See
testing/api-surface-validation.test.tsfor MCP tool testing - See
testing/batch-operations.test.tsfor performance testing
Related Documentation:
- Memory Persistence Test Summary - Detailed test results
- Repository Instructions - Development workflow
- README - Project overview
Last Updated: 2025-10-13
Maintained by: Repository development team