Hone logo
Hone
Problems

Achieve 100% Line Coverage in Jest Tests

This challenge focuses on ensuring that every executable line of code in your application is run at least once by your Jest test suite. Achieving high line coverage is a crucial step towards writing robust and well-tested software, as it helps identify dead or untested code.

Problem Description

Your task is to implement a simple JavaScript function and then write Jest tests for it that achieve 100% line coverage. You will need to configure Jest to report coverage and analyze the results to identify any lines that are not being executed by your tests.

What needs to be achieved:

  1. Create a TypeScript function: Implement a small, illustrative TypeScript function. This function should have a few branches (e.g., if/else, switch, loops) to make coverage analysis interesting.
  2. Write Jest tests: Develop a suite of Jest tests for the created function.
  3. Configure Jest for coverage: Ensure Jest is set up to generate coverage reports.
  4. Achieve 100% line coverage: Modify your tests until the Jest coverage report indicates that every executable line in your function has been covered.

Key Requirements:

  • The function should be written in TypeScript.
  • Tests should be written using Jest.
  • Coverage reports should be generated using Jest's built-in coverage capabilities.
  • The final test suite must result in 100% line coverage for the provided function.

Expected Behavior:

When you run jest --coverage (or a similar command configured in your jest.config.js), the output should show 100% line coverage for the file containing your TypeScript function.

Edge Cases to Consider:

  • Ensure all branches of conditional statements are tested.
  • Test different inputs that might lead to different execution paths.
  • Consider what happens with "empty" or "zero" inputs if applicable to your function.

Examples

Example 1: Simple Function

Consider a function that checks if a number is positive, negative, or zero.

// src/numberChecker.ts
export function checkNumber(num: number): string {
  if (num > 0) {
    return "Positive";
  } else if (num < 0) {
    return "Negative";
  } else {
    return "Zero";
  }
}

Tests to achieve 100% coverage for Example 1:

// src/numberChecker.test.ts
import { checkNumber } from "./numberChecker";

describe("checkNumber", () => {
  test("should return 'Positive' for a positive number", () => {
    expect(checkNumber(10)).toBe("Positive");
  });

  test("should return 'Negative' for a negative number", () => {
    expect(checkNumber(-5)).toBe("Negative");
  });

  test("should return 'Zero' for zero", () => {
    expect(checkNumber(0)).toBe("Zero");
  });
});

Explanation:

Each test block in the example above targets a specific if/else if/else condition, ensuring that all executable lines within the checkNumber function are run.

Example 2: Function with a Loop

Consider a function that calculates the sum of an array of numbers.

// src/arraySummer.ts
export function sumArray(arr: number[]): number {
  let sum = 0;
  for (const num of arr) {
    sum += num;
  }
  return sum;
}

Tests to achieve 100% coverage for Example 2:

// src/arraySummer.test.ts
import { sumArray } from "./arraySummer";

describe("sumArray", () => {
  test("should return the correct sum for an array of positive numbers", () => {
    expect(sumArray([1, 2, 3])).toBe(6);
  });

  test("should return the correct sum for an array with negative numbers", () => {
    expect(sumArray([1, -2, 3])).toBe(2);
  });

  test("should return 0 for an empty array", () => {
    expect(sumArray([])).toBe(0);
  });
});

Explanation:

The tests cover a standard array, an array with mixed positive and negative numbers, and importantly, an empty array. The empty array test ensures that the for...of loop's body is skipped, but the line returning sum (which is initialized to 0) is still covered.

Constraints

  • The TypeScript function should be no more than 20 lines of executable code (excluding comments and blank lines).
  • The Jest test suite should be reasonably concise, aiming to test the core logic of the function without excessive boilerplate.
  • You are expected to use standard Jest configuration for coverage reporting.

Notes

  • You will need to have Node.js, npm/yarn, TypeScript, and Jest installed.
  • Create a jest.config.js file and configure it to include coverage reporting. A common configuration for coverage would look like:
    // jest.config.js
    module.exports = {
      preset: 'ts-jest',
      testEnvironment: 'node',
      collectCoverage: true,
      coverageDirectory: 'coverage',
      coverageReporters: ['text', 'html'],
      testMatch: ['**/__tests__/**/*.ts?(x)', '**/?(*.)+(spec|test).ts?(x)'],
    };
    
  • To run tests and generate coverage, you'll typically use a command like npm test or yarn test if you have a script set up in your package.json (e.g., "test": "jest --coverage").
  • Analyze the coverage/lcov-report/index.html file to see a detailed breakdown of which lines are covered.
  • Focus on writing tests that logically cover different execution paths within your function. Don't just add redundant tests for the sake of coverage if they don't test a new scenario.
Loading editor...
typescript