Today I Learned

A Zero One initiative

`has_secure_password` can slow test suites down

TL;DR - A small BCrypt config tweak improved our test suite runtime from 3.5mins to 15s!

We have a project that had unusually slow tests compared to other systems.

~1000 tests took 3.5 minutes to run, which is unacceptably slow.

We did some profiling using Test Prof which pointed to factories being the culprit, but it was difficult to drill down further and get a clear answer.

After some further digging, we found the problem:

# in spec/factories/users.rb

password_digest { BCrypt::Password.create(Faker::Internet.password) }

BCrypt is slow by design, mainly to make offline rainbow table attacks unfeasible, but in most cases during testing, we don’t need to worry about that.

We can configure BCrypt to “spend less” resources when creating a password for a user in a factory by adding the following config to either config/environments/test.rb or spec/rails_helper.rb:

# Configure BCrypt to use minimum cost in tests to avoid needless slowdowns
BCrypt::Engine.cost = BCrypt::Engine::MIN_COST

This is similar to configuring Devise’s “stretches” to 1 for testing.

Our test suite runtime improved ~14x from 3.5mins to 15secs from this one simple change.

Looking for help? Each developer at Zero One has years of experience working with Ruby applications of all types and sizes. We're an active presence at Ruby conferences, and have worked on many of the web's Ruby on Rails success stories. Contact us today to talk about your Ruby project.