tests — tests

Module: tests-tests Cohesion: 0.80 Members: 0

tests — tests

This document provides an overview of the testing suite for Code Buddy, located in the tests/ directory. It covers the testing framework, structure, common patterns, and best practices to help developers understand, write, and contribute to the test codebase.

1. Introduction

The tests/ directory houses the comprehensive test suite for Code Buddy. Its primary purpose is to ensure the reliability, correctness, and security of the application's various components, from core utilities and AI agent logic to security features and user interfaces.

2. Testing Framework

Code Buddy uses Jest as its primary testing framework, with full TypeScript support provided by ts-jest. This combination allows for robust, type-safe tests that integrate seamlessly with the project's development environment.

3. Running Tests

Tests can be executed using standard npm scripts:

    npm test
    npm run test:watch
    npm run test:coverage

To view the detailed coverage report in your browser:

    open coverage/lcov-report/index.html

4. Test Structure

The tests/ directory is organized to mirror the src/ directory, making it easy to locate tests for specific modules.

tests/
├── utils/              # Utility function tests
│   ├── cache.test.ts       # Cache system tests
│   ├── errors.test.ts      # Error handling tests
│   └── model-utils.test.ts # Model utilities tests
├── agent/              # Agent-related tests (e.g., parallel executor, architect mode)
├── security/           # Security feature tests (e.g., approval modes, data redaction)
├── performance/        # Performance benchmarking tests
├── ...                 # Other categories mirroring src/
└── README.md           # This file

Test files are named with a .test.ts suffix (e.g., my-module.test.ts for src/utils/my-module.ts).

5. Writing Tests

When contributing to Code Buddy, adhere to the following best practices and common patterns.

5.1. General Best Practices

  1. One test file per source file: Name test files with .test.ts suffix, corresponding to the source file (e.g., src/module.ts -> tests/module.test.ts).
  2. Descriptive test names: Use it('should ...') format to clearly state the expected behavior.
  3. Group related tests: Use describe() blocks to logically group tests for a specific function, class, or feature.
  4. Test edge cases: Include tests for error conditions, boundary cases, and unexpected inputs.
  5. Use setup/teardown: Leverage beforeEach() and afterEach() for common setup and cleanup tasks, ensuring test isolation.
  6. Mock external dependencies: Isolate unit tests from external systems (e.g., file system, network, AI APIs) using Jest's mocking capabilities.

5.2. Asynchronous Code

Jest provides excellent support for asynchronous tests using async/await:

it('should handle async operations', async () => {
  const result = await asyncFunction();
  expect(result).toBe('success');
});

it('should handle rejections', async () => {
  await expect(failingAsync()).rejects.toThrow('error message');
});

5.3. Mocking

Mocking is crucial for isolating units of code and controlling external behavior.

    jest.mock('../../src/utils/some-module');
    class="hl-cmt">// ... then import the mocked module
    import { someFunction } from '../../src/utils/some-module';
    class="hl-cmt">// (someFunction as jest.Mock).mockReturnValue('mocked value');
    const mockFn = jest.fn();
    mockFn.mockReturnValue('mocked value');
    mockFn.mockResolvedValue('async mocked value'); class="hl-cmt">// For async functions
    class="hl-cmt">// ...
    expect(mockFn).toHaveBeenCalledTimes(1);
    expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
    jest.mock('fs-extra', () => {
      const impl = {
        ensureDir: jest.fn().mockResolvedValue(undefined),
        pathExists: jest.fn().mockResolvedValue(false),
        readJSON: jest.fn().mockResolvedValue({}),
        writeJSON: jest.fn().mockResolvedValue(undefined),
        class="hl-cmt">// ... other fs-extra methods
      };
      return { ...impl, default: impl }; class="hl-cmt">// Handle default export
    });
    jest.mock('../src/codebuddy/client.js', () => ({
      CodeBuddyClient: jest.fn().mockImplementation(function() { return {
        chat: jest.fn().mockResolvedValue({
          choices: [{ message: { content: 'Mocked AI response' } }],
        }),
      }; }),
    }));

5.4. Testing Singletons

Many core services in Code Buddy are implemented as singletons (e.g., AdvancedParallelExecutor, AnalyticsDashboard, BenchmarkSuite). A common pattern for testing these involves:

  1. Using a reset function (e.g., resetAdvancedParallelExecutor()) in beforeEach to ensure a fresh instance for each test.
  2. Verifying that get...() functions return the same instance.
  3. Verifying that reset...() indeed creates a new instance.
describe('AdvancedParallelExecutor', () => {
  beforeEach(() => {
    resetAdvancedParallelExecutor(); class="hl-cmt">// Ensure fresh state
    executor = new AdvancedParallelExecutor(...);
  });

  it('should return same instance', () => {
    const instance1 = getAdvancedParallelExecutor();
    const instance2 = getAdvancedParallelExecutor();
    expect(instance1).toBe(instance2);
  });

  it('should reset correctly', () => {
    const instance1 = getAdvancedParallelExecutor();
    resetAdvancedParallelExecutor();
    const instance2 = getAdvancedParallelExecutor();
    expect(instance1).not.toBe(instance2);
  });
});

5.5. Event Testing

Many Code Buddy components emit events. Jest's jest.fn() combined with Promise can be used to test event emissions:

it('should emit parallel:start event', async () => {
  const event = new Promise<void>((resolve, reject) => {
    executor.once(&#39;parallel:start&#39;, (data) => {
      try {
        expect(data.taskCount).toBeDefined();
        resolve();
      } catch (error) {
        reject(error);
      }
    });
  });

  const execution = executor.executeParallel([...]);
  await Promise.all([event, execution]); class="hl-cmt">// Wait for both event and execution
});

5.6. Platform-Specific Tests

Some tests, particularly those involving file paths or shell commands, might behave differently on Windows vs. Unix-like systems. The itUnix helper (or similar conditional logic) is used to skip tests on incompatible platforms:

const isWin = process.platform === &#39;win32&#39;;
const itUnix = isWin ? it.skip : it;

itUnix(&#39;should allow cat on safe files&#39;, async () => {
  class="hl-cmt">// ... test logic
});

6. Key Test Areas and Examples

The test suite covers a wide range of functionalities, demonstrating various testing approaches.

6.1. AdvancedParallelExecutor (tests/advanced-parallel-executor.test.ts)

6.2. AITestRunner (tests/ai-integration-tests.test.ts)

6.3. AnalyticsDashboard (tests/analytics-dashboard.test.ts)

6.4. ApprovalModeManager (tests/approval-modes.test.ts)

6.5. ArchitectMode (tests/architect-mode.test.ts)

6.6. BashTool (tests/bash-tool.test.ts)

6.7. BenchmarkSuite (tests/benchmark-suite.test.ts)

6.8. CheckpointManager (tests/checkpoint-manager.test.ts)

6.9. CodeReviewEngine (tests/code-review.test.ts)

6.10. ComputerSkills — LLM Step (tests/computer-skills-llm.test.ts)

6.11. ConfigValidator (tests/config-validator.test.ts)

6.12. ContextManagerV2 (tests/context-manager-v2.test.ts)

6.13. DataRedactionEngine (tests/data-redaction.test.ts)

6.14. Database System (tests/database.test.ts)

7. Coverage Goals

Code Buddy aims for high test coverage to ensure quality. The following targets are set:

Developers are encouraged to run coverage reports (npm run test:coverage) to identify gaps when adding new features or fixing bugs.

8. Continuous Integration

Tests are automatically run on every push via GitHub Actions. All pull requests must have passing tests before they can be merged, enforcing a high standard of code quality.

9. Troubleshooting

10. Resources