InsecureRandom

Gem Version Build Status Code Climate Coverage Status Dependency Status

InsecureRandom overwrites SecureRandom to enable predictability via seeding.

Why?

RSpec

RSpec has a fantastic feature that allows you to run your tests in random order.

rspec --order=random

Running tests in random order helps you find potential ordering dependencies in your test suite. For example, Test A and Test B both pass when run in that order, but Test A fails if Test B runs first.

Your test suite should not depend on the order in which the tests are run.

If an ordering dependency causes a test failure, you can rerun the tests in the same order using the seed from the previous run.

rspec --seed=93487

RSpec does this by seeding and using Kernel.rand to order your specs. This has the handy side effect of making other random test data reproducible as well. For example, your Factory Girl factories might use random data via Faker.

FactoryGirl.define do
  factory :user do
    name { Faker::Name.name }
    age { rand(100) }
  end
end

Since Faker uses Kernel.rand under the hood, your test data will be consistent across seeded RSpec runs.

SecureRandom

But what happens when generating random data isn't confined to your test suite?

Sometimes, it's necessary to generate random values for UUIDs, API keys, URL slugs, etc. The SecureRandom module is perfect for those situations. SecureRandom uses secure pseudorandom generators from tried and tested libraries such as OpenSSL.

The Problem

The problem with testing code that involves SecureRandom is that SecureRandom isn't seedable, which means that RSpec isn't able to rerun your tests in a predictable way.

The Solution

Fortunately, SecureRandom only defines a handful of methods so it's easy to override them to be backed by Kernel.rand.

And it gets even better. All of SecureRandom's methods are derived from SecureRandom.random_bytes so overriding just that one method does the trick!

Installation

Add InsecureRandom to your Gemfile's test group:

group :development, :test do
  gem "insecure_random"
end

Make sure that InsecureRandom is not loaded in production!