CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-jest-runner

Jest's test runner responsible for orchestrating test execution, managing worker processes, and coordinating parallel test runs

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

worker-management.mddocs/

Worker Process Management

Worker setup and execution functions for parallel test processing across multiple worker processes. This system enables Jest to run tests concurrently while maintaining isolation and providing efficient resource management.

Capabilities

Worker Setup Function

Initializes worker processes with serialized resolvers and module maps for efficient test execution.

/**
 * Set up worker processes with necessary resolvers and module maps
 * Called once per worker process during initialization
 * @param setupData - Configuration data containing serializable resolvers
 */
export function setup(setupData: {
  serializableResolvers: Array<SerializableResolver>;
}): void;

Usage Example:

The setup function is internal to the jest-runner package and called automatically by the worker process management system. It is not part of the public API:

// This is called internally by TestRunner when spawning workers
// Users do not need to call this directly

Worker Execution Function

Executes individual tests within worker processes with proper context deserialization and error handling.

/**
 * Execute a test within a worker process
 * @param workerData - Test execution data including config and context
 * @returns Promise resolving to test results
 */
export async function worker(workerData: {
  config: Config.ProjectConfig;
  globalConfig: Config.GlobalConfig;
  path: string;
  context: TestRunnerSerializedContext;
}): Promise<TestResult>;

Usage Example:

The worker function is internal to the jest-runner package and called automatically by the worker process management system. It is not part of the public API:

// This is called internally by TestRunner via jest-worker
// Users do not need to call this directly

Worker Process Architecture

The worker system is designed for efficient parallel test execution with proper isolation and resource management.

Worker Lifecycle:

  1. Process Creation: jest-worker spawns worker processes
  2. Setup Phase: setup() initializes resolvers and module maps
  3. Test Execution: worker() processes individual test requests
  4. Communication: Bidirectional messaging between main and worker processes
  5. Cleanup: Graceful shutdown with resource deallocation

Process Isolation:

  • Each worker runs in a separate Node.js process
  • Independent module resolution and caching per worker
  • Isolated global state and environment variables
  • Memory usage tracking and limits per worker

Resolver Management

Efficient resolver setup and caching for module resolution within worker processes.

/**
 * Serializable resolver data for worker processes
 */
interface SerializableResolver {
  config: Config.ProjectConfig;
  serializableModuleMap: SerializableModuleMap;
}

Resolver Caching: The setup function creates and caches resolvers for each project configuration:

// Internal resolver caching (not exported)
const resolvers = new Map<string, Resolver>();

// Resolver creation from serialized module maps
for (const { config, serializableModuleMap } of setupData.serializableResolvers) {
  const moduleMap = HasteMap.getStatic(config).getModuleMapFromJSON(serializableModuleMap);
  resolvers.set(config.id, Runtime.createResolver(config, moduleMap));
}

Context Serialization

Proper serialization and deserialization of test runner context for worker communication.

/**
 * Serialized version of TestRunnerContext for worker processes
 * Converts Sets to Arrays for JSON serialization
 */
interface TestRunnerSerializedContext {
  changedFiles?: Array<string>;
  sourcesRelatedToTestsInChangedFiles?: Array<string>;
}

/**
 * Serialized setup data passed to worker processes during initialization
 */
interface SerializableResolver {
  config: Config.ProjectConfig;
  serializableModuleMap: SerializableModuleMap;
}

Context Conversion: The worker function converts serialized arrays back to Sets:

// Convert serialized context back to Sets
const context: TestRunnerContext = {
  ...workerData.context,
  changedFiles: workerData.context.changedFiles && new Set(workerData.context.changedFiles),
  sourcesRelatedToTestsInChangedFiles: workerData.context.sourcesRelatedToTestsInChangedFiles &&
    new Set(workerData.context.sourcesRelatedToTestsInChangedFiles)
};

Error Handling and Communication

Robust error handling with proper serialization for cross-process communication.

Error Formatting:

interface SerializableError {
  code?: string;
  message: string;
  stack?: string;
  type: string;
}

/**
 * Format errors for serialization across process boundaries
 */
const formatError = (error: string | ErrorWithCode): SerializableError => {
  if (typeof error === 'string') {
    const { message, stack } = separateMessageFromStack(error);
    return { message, stack, type: 'Error' };
  }
  
  return {
    code: error.code || undefined,
    message: error.message,
    stack: error.stack,
    type: 'Error'
  };
};

Uncaught Exception Handling: Workers install global error handlers to prevent crashes:

process.on('uncaughtException', err => {
  if (err.stack) {
    console.error(err.stack);
  } else {
    console.error(err);
  }
  exit(1); // Uses exit-x for proper cleanup
});

Worker Communication Protocol

The worker system uses jest-worker's messaging system for communication between main and worker processes.

Message Flow:

  1. Main → Worker: Test execution requests with serialized data
  2. Worker → Main: Real-time events during test execution
  3. Worker → Main: Final test results or error information
  4. Main ↔ Worker: Bidirectional custom message handling

Event Forwarding: Workers can send events back to the main process during test execution:

// Send events from worker to main process
const sendMessageToJest: TestFileEvent = (eventName, args) => {
  messageParent([eventName, args]);
};

// Events are forwarded through the communication channel
await runTest(path, globalConfig, config, resolver, context, sendMessageToJest);

Worker Configuration Options

Workers support various configuration options for optimal performance and resource management.

Worker Creation Options:

  • enableWorkerThreads: Use worker threads instead of child processes
  • exposedMethods: Methods available for calling from main process
  • forkOptions: Node.js child process options including serialization mode
  • idleMemoryLimit: Memory limit for idle workers
  • maxRetries: Maximum retry attempts for failed operations
  • numWorkers: Number of worker processes to spawn
  • setupArgs: Arguments passed to setup function

Memory Management: Workers can be configured with memory limits and monitoring:

// Worker memory limit configuration
idleMemoryLimit: typeof globalConfig.workerIdleMemoryLimit === 'number'
  ? globalConfig.workerIdleMemoryLimit
  : undefined

Process Cleanup and Shutdown

Proper cleanup procedures ensure workers shut down gracefully without resource leaks.

Graceful Shutdown:

  • Workers respond to shutdown signals from main process
  • Resources are properly deallocated before process termination
  • Force-exit detection and warning for stuck processes

Resource Management:

  • Module caches are cleared on shutdown
  • File handles and network connections are closed
  • Memory is released through garbage collection

Types

interface WorkerData {
  config: Config.ProjectConfig;
  globalConfig: Config.GlobalConfig;
  path: string;
  context: TestRunnerSerializedContext;
}

interface SerializableModuleMap {
  duplicates: ReadonlyMap<string, DuplicatesSet>;
  map: ReadonlyMap<string, ModuleMapItem>;
  mocks: ReadonlyMap<string, string>;
  rootDir: string;
}

interface ModuleMapItem {
  [platform: string]: ModuleMapData;
}

interface ModuleMapData {
  [key: string]: string;
}

interface DuplicatesSet {
  [key: string]: {[key: string]: number};
}

interface ErrorWithCode extends Error {
  code?: string;
}

type TestFileEvent = (
  eventName: string,
  args: Array<any>
) => void | Promise<void>;

docs

core-execution.md

custom-runner.md

index.md

test-runner.md

worker-management.md

tile.json