Jujutsu and Jest: only test changed code

In a standard git repo you can run jest --watch and jest --onlyChanged to only run the tests for the files that you’ve changed.

However if you’re using jj instead of git you’ll get this error:

$ yarn jest --watch

Determining test suites to run...
--watch is not supported without git/hg, please use --watchAll

Here’s how we can work around that.

Building block 1: the changed file paths

jj diff --name-only gives us just the path of each changed file.

$ jj diff --name-only
apps/native/src/app/index.tsx
apps/native/src/components/component-a.tsx
apps/native/src/components/component-b.tsx

Building block 2: passing the file paths to jest

Passing just those file paths on their own to Jest won’t work. We want Jest to run the tests related to the code we’ve changed, and by default if you give Jest a file path it assumes it’s a test file and tries to just run it directly.

Instead the --findRelatedTests flag is what we’re after:

jest --findRelatedTests fileA.ts fileB.ts

Piecing it together

We can glue the two together nicely using xargs:

jj diff --name-only | xargs yarn test --findRelatedTests

You might want to add a shell alias or script to make this more convenient, but still it works nicely.

Adding back --watch support

Piping to jest --watch breaks the interactivity (the › Press f to run only failed tests. stuff). So instead we can use command substitution:

# Fish shell
yarn test --watch --findRelatedTests (jj diff --name-only)

# Bash
yarn test --watch --findRelatedTests $(jj diff --name-only)