Hone logo
Hone
Problems

Delta Debugging with Jest: Isolating Faulty Test Cases

Delta debugging is a powerful technique for automatically shrinking failing test suites to isolate the smallest possible set of inputs that still cause a failure. This challenge asks you to implement a simplified version of delta debugging within a Jest testing environment. The goal is to identify the minimal changes needed to a test case input that will make it pass, given a failing test.

Problem Description

You are provided with a Jest test suite that contains a failing test case. Your task is to implement a function deltaDebug that takes the failing test case function, the original input to that test case, and a function that modifies the input based on a given delta (a set of changes). The deltaDebug function should iteratively shrink the input by applying different deltas until a passing test case is found. The function should return the minimal input that makes the test pass.

Key Requirements:

  • Input Modification: The deltaDebug function will receive a modifyInput function. This function takes the original input and a delta (an array of changes) and returns a modified input.
  • Test Execution: The deltaDebug function must execute the provided test case function with the modified input.
  • Shrinking Strategy: The function should employ a simple shrinking strategy: start with a large delta (all possible changes), and progressively reduce the delta size until a passing test is found.
  • Minimal Input: The function should return the smallest input that makes the test pass. "Smallest" here means the input that requires the fewest changes from the original input to pass.
  • Jest Integration: The test case function is a standard Jest test function.

Expected Behavior:

The deltaDebug function should return an input that, when passed to the test case function, results in the test passing. The returned input should be the smallest modification of the original input that achieves this. If no passing input is found after a reasonable number of iterations, the function should return the original input.

Edge Cases to Consider:

  • No Delta Possible: If the modifyInput function cannot generate any meaningful deltas (e.g., the input is already at its minimum possible value), the function should return the original input.
  • Test Case Always Fails: If the test case always fails regardless of the input, the function should return the original input.
  • Complex Input Types: The input to the test case can be of any type (string, number, object, array, etc.). The modifyInput function must be able to handle these types.

Examples

Example 1:

// Original Test Case (simplified)
const testCase = (input: number) => {
  expect(input).toBe(5);
};

// Modify Input Function (simple example)
const modifyInput = (originalInput: number, delta: number[]) => {
  return originalInput + delta[0];
};

const originalInput = 3;

// Expected Output: 5
// Explanation: The original input is 3. The deltaDebug function should find that input 5 passes the test.

Example 2:

// Original Test Case (simplified)
const testCase = (input: string) => {
  expect(input).toBe("hello");
};

// Modify Input Function (simple example)
const modifyInput = (originalInput: string, delta: string[]) => {
  return originalInput + delta[0];
};

const originalInput = "hel";

// Expected Output: "hello"
// Explanation: The original input is "hel". The deltaDebug function should find that input "hello" passes the test.

Example 3: (Edge Case - No Delta Possible)

// Original Test Case (simplified)
const testCase = (input: number) => {
  expect(input).toBe(1);
};

// Modify Input Function (always returns the same input)
const modifyInput = (originalInput: number, delta: number[]) => {
  return originalInput;
};

const originalInput = 1;

// Expected Output: 1
// Explanation: The modifyInput function always returns the original input, so no changes are possible.

Constraints

  • Iteration Limit: The deltaDebug function should have a maximum iteration limit of 100 to prevent infinite loops.
  • Delta Size: The initial delta size should be based on the complexity of the input type. For simple types (number, string), start with a delta of +/- 1 or +/- 1 character. For objects, start with a delta that modifies one property.
  • Input Type: The input to the test case can be any valid JavaScript type.
  • Performance: The function should be reasonably efficient. Avoid unnecessary computations or memory allocations.

Notes

  • The modifyInput function is crucial. It defines how the input is modified. Consider how to design this function to allow for meaningful shrinking.
  • A simple shrinking strategy is sufficient for this challenge. More sophisticated strategies exist in real-world delta debugging implementations.
  • Focus on the core logic of shrinking the input and executing the test case. Error handling and extensive input validation are not required.
  • The goal is to demonstrate an understanding of the delta debugging concept within a Jest environment.
  • Consider how to handle different data types when generating deltas.
Loading editor...
typescript