Back to all articles

Parallel your specs and don’t waste time

Knapsack logo: a backpack with gems floating around it

A year ago, we started a new project.

As usual, the beginning was fun: small codebase, simple logic, and quick tests.

A few months of entropy later, our test suite reached 12 minutes.

That was annoying!

Static tests split

We chose the simple way out: throw money at the problem.

We added a few extra CI nodes and assigned an equal amount of test files each. Some specs, like unit tests, were quick and others, like end-to-end tests, took way more time.

That’s how we ended up with three fast CI nodes and one very slow:

Four parallel nodes on CI where one node took much longer

That’s when we took the problem seriously and started coding.

Dynamic tests split

We tried a few solutions, but found the best results by calculating the execution time of each test and splitting based on the last recorded times.

This strategy worked so well that I extracted Knapsack Pro into a gem, which owes its name to the Knapsack Problem.

Don’t waste your CI nodes’ time

With Knapsack Pro, our tests are split in the most efficient way so that each CI node finishes at the same time:

Four parallel nodes on CI where all nodes took a similar amount of time

Get started with Knapsack Pro

Add the gem to your project:

bundle add knapsack_pro --group "development, test"

Use the following code at the beginning of your spec/rails_helper.rb:

require 'knapsack_pro'
KnapsackPro::Adapters::RSpecAdapter.bind

Generate an API token and configure your CI server:

KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC=MY_API_TOKEN \
  bundle exec rake knapsack_pro:queue:rspec

Profit!

Oh, and one more thing, check the docs because Knapsack Pro comes with a truckload of additional features.

Share this article: