npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

jest-quarantine

v1.1.3

Published

> A quarantine method and reporter for [jest](https://jestjs.io/) to help quite flappy tests.

Downloads

524

Readme

jest-quarantine

A quarantine method and reporter for jest to help quite flappy tests.

Features

  • Use a new quarantine method to wrap test assertions in a try/catch
  • Opt in to using a date string to specify an expiration for a quarantined test or keep it there forever
  • Track pass/fail status and the it last ran for quarantined tests
  • Report on all the things in a test run:
    • the number of quarantined tests
    • which tests are quarantined (with a link back to the file)
    • whether or not quarantined tests passed

Motivation

Sometimes tests flap (pass -> fail -> pass -> etc) and we don't have the time at hand to fix them. We want to, or at least should, but we know enough to know that a proper fix isn't simple and will need to given dedicated time. In cases like these we want to have a way to easily quarantine tests so that they don't break builds, without skipping them or commenting them out, until we have a chance to properly address them.

The underlying idea

Unfortunately jest doesn't have a quarantine mechanism built in so we're often left to come up with our own approaches. Some of these commonly include:

  • run it again until it passes - which isn't ideal because it wastes resources and doesn't address the actual issue in any way
  • skip the test (using the skip method) - this isn't the worst but skipped tests are grouped together and don't get run so they often get forgotten
  • comment out the test - a bit worse than skipping because now there is no record of them unless someone goes to that file but again they're out of the way
  • mark it as todo (using the todo method) - this is nice approach since "todos" are reported separately but the method doesn't take a callback so we still have to change the underlying test and don't know if they would pass/fail during any given run
  • delete the test - not a big deal if we know we don't need it but when a test is flapping and preventing other planned work might not be the best time to make that determination

To be fair none of these are bad in their own right - they are totally appropriate cases, except maybe for choosing any of them without cursory investigation, but they just aren't ideal. What we might prefer is to run the test, prevent it from blocking if it fails, let it through like normal if it passes, and to report on all the results in some way.

Introducing jest-quarantine

That's where jest-quarantine comes in, or at least where it attempts to help. In a nutshell, it gives us more flexibility so that when we run into flapping tests, and unfortunately we will, we aren't pigeonholed into fixing it or ignoring it but rather we can add it a new unique set of tests that we can track and easily come back to.


Installation

| NPM | Yarn | | -------------------------------- | ----------------------------- | | npm install -D jest-quarantine | yarn add -D jest-quarantine |

Quick setup

If all you care about is quarantining tests, and you don't need/want any reporting, then you can just import the quarantine method and use it in place of it/test where you need it.

// some-test-file.spec.js
import { quarantine } from "jest-quarantine";

quarantine("a test that fails but will be quarantined forever", () => {
  expect(1).toBe(2);
});

quarantine(
  "a test that fails but will only be caught until a certain date",
  "2023-01-01",
  () => {
    expect(1).toBe(2);
  }
);

In this case our first quarantined test will stay quarantined forever while the second will start being run as normal after "2023-01-01" and any flapping behavior it has will affect test runs again.

Note: you can also follow the directions for using setupQuarantine below if you'd like for the quarantine method to exist in the global space but don't want reporting.

Kitchen sink setup

If on the other hand you want quarantining as well as reporting we also need to call the setup method. This is good case for anyone who wants to surface quarantined results during local runs or possibly store the output as a build artifact that can be tracked over time.

To do so we need to call setupQuarantine in any file already being passed to setupFilesAfterEnv. This will:

  • add the new quarantine method to the global space
  • set up the required tracking array
  • and save the results to a combined tracking log as a part of afterAll
// jest.testSetup.js - which is run via setupFilesAfterEnv
import { setupQuarantine } from "jest-quarantine";
setupQuarantine();

Then hook up the reporter in the jest config if you want to surface the results locally (not required, just helpful). See the reporter details below for a basic configuration.

reporters: [
    "default",
    ["jest-pseudo-quarantine/reporter.js", { enabled: true, showTests: true }],
],

An example of the quarantine reporter's output with all the options in use can be seen below. In this case:

  • we have the "default" jest reporter on which tells us that 1 suite, with 10 tests, of which 8 passed, and 2 were "todos"
  • below that default output we get:
    • a quarantined count, which was 2 and since it uses "todo" internally is the reason those counts exist
    • a list of the file that was run, the test name in it that was quarantined, and the result of attempting to run it

Reporter options

| Option | Type | Default | Description | | ---------- | ------- | ------- | ------------------------------------------------------------------------------- | | enabled | boolean | true | Turns on/off the reporter | | showTests | boolean | false | Shows which tests were quarantined in the output and whether or not they passed | | colorLevel | number | 2 | Determines whether or not the output has color | | logger | object | console | Determines where to log output to |

Exported methods

| Method | Use | | --------------- | ------------------------------------------------------------------------------------- | | quarantine | Can be used as a replacement to it/test/jest.test. | | setupQuarantine | Adds the quarantine method and an array for tracking results to the global space. |

Generated files

Multiple files are created while saving results:

  • quarantined-tests/test/file/path/and/name.log = used to store quarantine results for a single file
  • quarantined-tests/combined-results.log = used to store all of the results combined and should be added to your .gitignore

Regardless of whether you are looking at the logs for an individual file or the combined results they both follow the same format and contain an array of objects with the following properties:

| Property | Type | Description | | -------- | ------- | ------------------------------------------------------------- | | name | string | The test name passed to quarantine | | passes | boolean | Whether or not the supplied function's assertions passed | | testPath | string | The relative path to the log file where the test can be found | | date | string | The date/time when the test was run |

For example:

[
  {
    "name": "some test",
    "passes": false,
    "testPath": "spec/javascripts/a/folder/spec.js",
    "date": "2022-01-30T19:20:40.950Z"
  },
  {
    "name": "another test",
    "passes": true,
    "testPath": "spec/javascripts/a/folder/elsewhere/spec.js",
    "date": "2022-01-30T19:20:47.436Z"
  }
]

Caveats

The quarantine method doesn't currently support the timeout argument

This could be added in at any point, especially if someone has a strong need and is willing to open a PR for it, however we simply don't use that option and so it's not baked in.

Jest doesn't expose suite names

Because of this the stored test names are only those that are passed directly to quarantine and doesn't include the suite bane - which means the output for a given file will be harder to parse if you don't have unique test names. For example:

// some-spec.js
describe("Calendar", () => {
  describe("with option A on", () => {
    quarantine("does something", () => ...);
  });

  describe("with option A off", () => {
    quarantine("does something", () => ...);
  });
});

which would result in output like this:

Quarantined: 2 total
  some-spec.js
  --> does something - passes: false
  some-spec.js
  --> does something - passes: false

Contributing

First off, thank you for considering contributing. We are always happy to accept contributions and will do our best to ensure they receive the appropriate feedback.

Things to know:

  • Commits are required to follow the Conventional Commits Specification.
  • There is no planned/automated cadence for releases. Because of this once changes are merged they will be manually published, at least for the time being.

Making changes/improvements

To contribute changes:

  • Fork the repo
  • Create your feature branch (git checkout -b my-new-feature)
  • Make, test, and commit your changes (git commit -am 'feat: Add some feature')
  • Push to the branch (git push origin my-new-feature)
  • Create a new Pull Request

Note: only changes accompanied by tests will be considered for merge.

Reporting issues

If you encounter any issue please feel free to open a new ticket and report it.