Skip to main content

Knapsack Pro Jest: Quickstart

Create an account to generate API tokens and use Knapsack Pro.

Installation

Make sure you have jest in your package.json because @knapsack-pro/jest uses the version installed in your project.

npm install --save-dev @knapsack-pro/jest

Now, fill in the following form to generate the instruction steps for your project:

What is your CI provider?

Do you use Create React App?

Instructions

AppVeyor

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

For each parallel job, define:

Remember to configure the number of parallel CI nodes in AppVeyor.

KNAPSACK_PRO_CI_NODE_TOTAL=N \
KNAPSACK_PRO_CI_NODE_INDEX=0 \
KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN \
npx knapsack-pro-jest --runInBand

Buildkite

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Remember to configure the parallelism parameter in your build step.

npx knapsack-pro-jest --runInBand

When using the docker-compose plugin on Buildkite, you have to pass the following environment variables:

steps:
- label: "Test"
parallelism: 2
plugins:
- docker-compose#3.0.3:
run: app
command: npx knapsack-pro-jest --runInBand
config: docker-compose.test.yml
env:
- BUILDKITE
- BUILDKITE_PARALLEL_JOB_COUNT
- BUILDKITE_PARALLEL_JOB
- BUILDKITE_BUILD_NUMBER
- BUILDKITE_COMMIT
- BUILDKITE_BRANCH
- BUILDKITE_BUILD_AUTHOR
- BUILDKITE_BUILD_CREATOR

Here you can find an article on how to set up a new pipeline for your project in Buildkite and configure Knapsack Pro.

You can also check out the following example repositories for Ruby on Rails projects:

CircleCI

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Remember to add additional parallel containers in the CircleCI settings.

.circleci/config.yml
jobs:
build:
parallelism: 2

steps:
- checkout

# ...

- run:
name: jest with @knapsack-pro/jest
command: npx knapsack-pro-jest --runInBand

Here you can find an example of a Rails project config on CircleCI 2.0.

Cirrus CI

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Configure the number of parallel CI nodes with the matrix modification:

.cirrus.yml
task:
environment:
KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST: ENCRYPTED[KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST]
matrix:
name: CI Node 0
name: CI Node 1
name: CI Node 2
test_script:
- npx knapsack-pro-jest --runInBand

Remember to set up the KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST as an encrypted variable.

Here is an example of a .cirrus.yml configuration file for a Ruby project.

CloudBees CodeShip

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

For each parallel pipeline, define:

KNAPSACK_PRO_CI_NODE_TOTAL=N \
KNAPSACK_PRO_CI_NODE_INDEX=0 \
KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN \
npx knapsack-pro-jest --runInBand

Consider moving the KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST to the Environment page of your project settings in CodeShip.

Codefresh

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Define in .codefresh/codefresh.yml:

Remember to configure the YAML file path on Codefresh: Pipelines > Settings (cog icon next to the pipeline) > Workflow Tab (horizontal menu on the top) > Path to YAML > ./.codefresh/codefresh.yml.

Here's an example config:

.codefresh/codefresh.yml
version: "1.0"

stages:
- "clone"
- "build"
- "tests"

steps:
main_clone:
type: "git-clone"
description: "Cloning main repository..."
repo: "${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}"
revision: "${{CF_BRANCH}}"
stage: "clone"
BuildTestDockerImage:
title: Building Test Docker image
type: build
arguments:
image_name: "${{CF_ACCOUNT}}/${{CF_REPO_NAME}}-test"
tag: "${{CF_BRANCH_TAG_NORMALIZED}}-${{CF_SHORT_REVISION}}"
dockerfile: Test.Dockerfile
stage: "build"

run_tests:
stage: "tests"
image: "${{BuildTestDockerImage}}"
working_directory: /src
fail_fast: false
environment:
- KNAPSACK_PRO_CI_NODE_TOTAL=2
matrix:
environment:
- KNAPSACK_PRO_CI_NODE_INDEX=0
- KNAPSACK_PRO_CI_NODE_INDEX=1
commands:
- npx knapsack-pro-jest --runInBand

Consider setting up the KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST on the Codefresh dashboard: Pipelines > Settings (cog icon next to the pipeline) > Variables Tab (vertical menu on the right-hand side).

GitHub Actions

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Define in .github/workflows/main.yaml:

Here's an example config:

.github/workflows/main.yaml
name: Main

on: [push]

jobs:
test:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
node-version: [18.x]
ci_node_total: [2]
ci_node_index: [0, 1]

steps:
- uses: actions/checkout@v2

- name: Set up Node
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}

- name: Install and Build
run: |
npm install
npm run build --if-present

- name: Run tests
env:
KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST }}
KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }}
KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }}
run: |
npx knapsack-pro-jest --runInBand

GitLab CI

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

GitLab CI >= 11.5

test:
parallel: 2

script:
- KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN npx knapsack-pro-jest --runInBand

See also how to configure running parallel CI nodes in GitLab.

GitLab CI < 11.5

Define in .gitlab-ci.yml:

Here's an example configuration for 2 parallel jobs:

.gitlab-ci.yml
stages:
- test

variables:
KNAPSACK_PRO_CI_NODE_TOTAL: 2

test_ci_first_node:
stage: test
script:
- export KNAPSACK_PRO_CI_NODE_INDEX=0
- KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN npx knapsack-pro-jest --runInBand

test_ci_second_node:
stage: test
script:
- export KNAPSACK_PRO_CI_NODE_INDEX=1
- KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN npx knapsack-pro-jest --runInBand

Remember to set up the KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST as Secret Variables in GitLab CI: Settings > CI/CD Pipelines > Secret Variables.

Heroku CI

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Define in app.json:

app.json
{
"environments": {
"test": {
"formation": {
"test": {
"quantity": 2
}
},
"addons": [
"heroku-postgresql:in-dyno",
"heroku-redis:in-dyno"
],
"scripts": {
"test": "npx knapsack-pro-jest --runInBand"
},
"env": {
"KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST": "MY_JEST_API_TOKEN"
}
}
}
}

Remember to set up the KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST outside of app.json in your Heroku CI pipeline's settings.

Jenkins

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

In order to run parallel jobs with Jenkins you should use Jenkins Pipeline as described in Parallelism and Distributed Builds with Jenkins.

Here is an example of a Jenkinsfile working with Jenkins Pipeline:

timeout(time: 60, unit: 'MINUTES') {
node() {
stage('Checkout') {
checkout([/* checkout code from git */])

// determine git commit hash because we need to pass it to Knapsack Pro
COMMIT_HASH = sh(returnStdout: true, script: 'git rev-parse HEAD').trim()

stash 'source'
}
}

def num_nodes = 4; // define your total number of CI nodes (how many parallel jobs will be executed)
def nodes = [:]

for (int i = 0; i < num_nodes; i++) {
def index = i;
nodes["ci_node_${i}"] = {
node() {
stage('Setup') {
unstash 'source'
// other setup steps
}

def knapsack_options = """\
KNAPSACK_PRO_CI_NODE_TOTAL=${num_nodes}\
KNAPSACK_PRO_CI_NODE_INDEX=${index}\
KNAPSACK_PRO_COMMIT_HASH=${COMMIT_HASH}\
KNAPSACK_PRO_BRANCH=${env.BRANCH_NAME}\
KNAPSACK_PRO_CI_NODE_BUILD_ID=${env.BUILD_TAG}\
KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN
"""

stage('Run tests') {
sh """${knapsack_options} npx knapsack-pro-jest --runInBand"""
}
}
}
}

parallel nodes // run CI nodes in parallel
}

Consider setting up the KNAPSACK_PRO_TEST_SUITE_TOKEN_* as global environment variables in Jenkins.

Semaphore CI

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Define in .semaphore/semaphore.yml:

Here's an example config:

.semaphore/semaphore.yml
version: v1.0

name: My app

agent:
machine:
type: e1-standard-2
os_image: ubuntu1804

blocks:
- name: Jest tests
task:
env_vars:
- name: KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST
value: MY_JEST_API_TOKEN
prologue:
commands:
- checkout
- nvm install --lts hydrogen
- sem-version node --lts hydrogen

jobs:
- name: Run tests with Knapsack Pro
parallelism: 2
commands:
- npx knapsack-pro-jest --runInBand

Remember to set up KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST as a secret.

Travis CI

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Define in .travis.yml:

script:
- "npx knapsack-pro-jest --runInBand"

env:
global:
- KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN
- KNAPSACK_PRO_CI_NODE_TOTAL=3
jobs:
- KNAPSACK_PRO_CI_NODE_INDEX=0
- KNAPSACK_PRO_CI_NODE_INDEX=1
- KNAPSACK_PRO_CI_NODE_INDEX=2

Remember to set up KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST as tokens in the Travis settings to avoid exposing them in the build logs.

You can find more info about the global and matrix env configuration in the Travis' docs.

Other CI provider

Generate an API token for each Knapsack Pro command on the CI. Each command needs its own API token to treat every test suite as a separate entity.

Define the following global environment variables on your CI server:

KNAPSACK_PRO_CI_NODE_TOTAL=N \
KNAPSACK_PRO_CI_NODE_INDEX=0 \
KNAPSACK_PRO_CI_NODE_BUILD_ID=MY_BUILD_ID \
KNAPSACK_PRO_TEST_SUITE_TOKEN_JEST=MY_JEST_API_TOKEN \
npx knapsack-pro-jest --runInBand

Create React App

If you are using Create React App, make sure to:

  • Add the following to your package.json

    {
    ...,
    "jest": {
    "roots": [
    "<rootDir>/src"
    ],
    "collectCoverageFrom": [
    "src/**/*.{js,jsx,ts,tsx}",
    "!src/**/*.d.ts"
    ],
    "setupFiles": [
    "react-app-polyfill/jsdom"
    ],
    "setupFilesAfterEnv": [
    "<rootDir>/src/setupTests.ts"
    ],
    "testMatch": [
    "<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}",
    "<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}"
    ],
    "testEnvironment": "jsdom",
    "transform": {
    "^.+\\.(js|jsx|mjs|cjs|ts|tsx)$": "<rootDir>/node_modules/react-scripts/config/jest/babelTransform.js",
    "^.+\\.css$": "<rootDir>/node_modules/react-scripts/config/jest/cssTransform.js",
    "^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)": "<rootDir>/node_modules/react-scripts/config/jest/fileTransform.js"
    },
    "transformIgnorePatterns": [
    "[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$",
    "^.+\\.module\\.(css|sass|scss)$"
    ],
    "modulePaths": [],
    "moduleNameMapper": {
    "^react-native$": "react-native-web",
    "^.+\\.module\\.(css|sass|scss)$": "identity-obj-proxy"
    },
    "moduleFileExtensions": [
    "web.js",
    "js",
    "web.ts",
    "ts",
    "web.tsx",
    "tsx",
    "json",
    "web.jsx",
    "jsx",
    "node"
    ],
    "watchPlugins": [
    "jest-watch-typeahead/filename",
    "jest-watch-typeahead/testname"
    ],
    "resetMocks": true
    },
    "babel": {
    "presets": [
    "react-app"
    ]
    }
    }
    • call npx knapsack-pro-jest with the proper KNAPSACK_PRO_TEST_FILE_PATTERN (e.g., KNAPSACK_PRO_TEST_FILE_PATTERN="{**/*.test.ts?(x),**/?(*.)(test).ts?(x)}")

    Feel free to copy/paste from the create-react-app-example repository.

You need to explicitly tell Knapsack Pro to load the jest.config.js file if needed.

Verify that everything works

Push a new commit to your repository and visit your dashboard to make sure all your CI nodes were recorded successfully in Show build metrics > Show (build).

Congratulations! Now that Knapsack Pro knows the statistics of your test suite, your CI builds will be parallelized optimally.

Next up

Make sure you check out the Reference and Cookbook pages to fine-tune your Knapsack Pro setup.

Need help?

Get in touch!

We have helped TONS of teams and seen TONS of projects. We know each test suite is a different beast and we'd be happy to help you set up Knapsack Pro.