
I ran into the need to debug Jest tests running inside a Docker container recently and didn't find any clear instructions on how to do it. Turns out it's pretty easy when you have the right flags.
Project setup
Let's walk through creating the files necessary to demonstrate the remote debugging.
Node.js
Using the examples from Jest's "Getting Started ," create sum.js:
function sum(a, b) {
return a + b;
}
module.exports = sum;and sum.test.js:
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});Docker
Loosely following Node's "Dockerizing a Node.js web app ," create Dockerfile:
FROM node:lts
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm ci
# Bundle app source
COPY . .
CMD [ "node", "sum.js" ]and .dockerignore:
node_modules
npm-debug.lognpm
Fill out your package.json with the following scripts and dependencies:
{
"scripts": {
"test": "jest",
"test-debug": "node --inspect-brk=0.0.0.0 ./node_modules/jest/bin/jest.js",
"test-watch": "jest --watchAll",
"test-watch-debug": "node --inspect-brk=0.0.0.0 ./node_modules/jest/bin/jest.js --watchAll --runInBand"
},
"devDependencies": {
"jest": "latest"
}
}Now let's walk through each of those debug commands.
test-debug
node --inspect-brk=0.0.0.0 ./node_modules/jest/bin/jest.jsTo break down each part of the command:
nodeis required in order to enable--inspect-brk. Thejestcommand doesn't provide a way to turn on the inspector.--inspect-brkwill wait for a remote debugger to attach before executing the code. We're havingnodewait because the test will likely execute too fast for us to attach to it. The0.0.0.0IP means bind to all interfaces which is required for Docker networking../node_modules/jest/bin/jest.jsruns Jest just like it would with thejestcommand.
test-watch-debug
node --inspect-brk=0.0.0.0 ./node_modules/jest/bin/jest.js --watchAll --runInBandThis adds two extra flags to Jest:
--watchAllwatches for file changes and re-runs all tests when something changes.--runInBandcauses all tests to be run in the parent process rather than child processes. This is required for debugging the tests--watchAllruns after file changes.
Directory tree
After creating those 5 files you will end up with the directory tree:
.
├── .dockerignore
├── Dockerfile
├── package.json
├── sum.js
└── sum.test.jsRunning with Docker
First, build the container and tag it as sum:
docker build -t sum .Then we'll walk through the different Docker commands that change depending on which testing command we want.
test-debug in Docker
To run test-debug we have a fairly short command:
docker run -p 9229:9229 sum npm run test-debugdocker runto run a command in an already built image.-p 9229:9229to map the remote port 9229 to the local port 9229. This is necessary to attach your IDE or browser to the remotenodeinstance.sumbeing the name of our built image.npm run test-debugto run our test command.
This will start the container and wait for a debugger to be attached on port 9229, then execute the tests.
test-watch-debug in Docker
The --watchAll flag for Jest requires some additional Docker flags:
docker run -it -v "$(pwd):/usr/src/app" -p 9229:9229 sum npm run test-watch-debug-itto be able to interact with the process, to control Jest.-v "$(pwd):/usr/src/app"to mount the local host directory in the container so that file changes are visible in the container.
Like test-debug, this will start the container and wait for a debugger to be attached on port 9229, then execute the tests, but then it also watches for file changes and re-runs all tests when something changes.
Try running this command, wait for tests to execute the first time, then change sum.js or sum.test.js and see what happens.
Attaching a debugger
It would take too long to list out the instructions for each editor, so here are links to some popular ones:
Make sure to use localhost for the host and 9229 for the port.



