Mutation Testing in NodeJS

What is mutation testing?

If you are reading this, we assume you are using TDD or that your coverage is nearly of 100%. If you are not complying to this requirement, start by building a strong Unit/Integration Test harness. Without a good coverage you won't get a lot of value out of this practice.

Mutation testing is a way to check if your current tests (unit, integration, etc...) are precise enougth to catch random changes in your code base. The tool navigates through the code and creates mutants by modifying mostly conditions and values (such as constants or conditionals).

For instance:

return {code: this.value};

will generate several mutants:

return null;
return {};
return undefined;

For each mutated version of your code, the tests base will be run.

If the test is still green the mutant will tagged this mutant state as Survived, otherwise it will be tagged as Killed.

The objective is to have as much Killed mutants as possible, meaning the tests is covering most cases and that a change in the code will be catched by a unit test.

We will be using Stryker as an automation tool:

Now! Let's go kill some mutants!

Install Stryker dependencies

npm i -g stryker-cli
npm i -D stryker-html-reporter stryker-jest-runner stryker-typescript @stryker-mutator/core

Configure

stryker init

Change the stryker.conf.js file to avoid analysing .spec.ts files and add the plugins manually to avoid dependencies errors:

module.exports = function (config) {
  config.set({
    mutator: "typescript",
    packageManager: "npm",
    reporters: ['progress','html'],
    testRunner: "jest",
    transpilers: [],
    coverageAnalysis: "off",
    tsconfigFile: "tsconfig.json",
    mutate: ["src/**/*.ts", '!src/**/*.spec.ts'],
    htmlReporter: {
      baseDir: 'mutation'
    },
    plugins: ['stryker-html-reporter', 'stryker-jest-runner', 'stryker-typescript']
  });
};

Start the test (put your computer in a freezer!)

stryker run

As always if you need help ask a friend 😊

31