Minitest Helper Includes and Rails Fixtures
Contuining my love affair with Minitest and fixtures, I wanted to dive in to something deeper this time. Switching tools takes time to get used to and managing passwords was one of the bigger headaches I encountered.
Because plain text passwords are not stored in the database, but rather a
password_digest, I didn’t have a good way to fill in the login forms using Capybara to test against pages that require authentication.
I started with a simple
users.yml fixture that looked like this:
As mentioned above,
Bcrypt to encrypt the plain text passwords provided. The specific implementation to create the password digest is:
This method takes the plain text password (“password”) and encrypts it with what it calls the “cost”. It’s not terribly important for this article, but to save some speed, I’ve specified a cost of 4 — the minimum cost support by the
Bcrypt algorithm. The default is 10, which will make your production applications safer. However, for testing, we don’t care.
The result of the method above looks like this:
That output value is what’s being stored in our database when a user inputs and saves a password. From the application’s standpoint, we could print a value like this in to our fixtures, but what’s the fun in that?!?!
ERB in Fixtures
Since fixtures allow us to use ERB in them, we could provide the
Bcrypt method above to produce the password digest like so:
The downside is that the actual password (“password”) is here in plain text. To fill in our login form using Capybara, we don’t have a variable to access to the get the password — we literally have to type “password”. So this isn’t the most DRY thing in the world. While it would certainly work, I think we can do better…
Let’s say I have a test that looks like this:
Extract a Module
Our goal was to not sprinkle these plan text passwords all over the place. So let’s extract a module call
TestPasswordHelper and put the plain text password in there:
We’ll have our default password accessible via a method named…get this,
default_password! The module also contains a method (
default_password_digest) that will allow us to send the password digest to the fixture using the Bcrypt algorithm we explored above.
Now that we have a helper module ready all set up, we add the following to our
test/test_helper.rb to make these methods accessible in our tests:
With these methods mixed in, we can update our Capybara test to use the
Helpers in Fixtures
Unfortunately, those helpers aren’t available in the fixtures.
ActiveRecord::FixtureSet is the class that gives our fixtures life. We can use Ruby to include functionality from our test helper, that will give us access to to the
default_password_digest method, which reads our
default_password so we don’t have to type it out.
The Rails API guide for fixtures states that helper methods should be added to
So back in our
test_helper.rb, we can mix in our test helpers methods like so:
Now, back in our
users.yml fixture, we can use the new
We can now run our tests and verify the fixtures properly insert the digest using the default password and the Capybara tests reference that same default password.
Now, if in the future we wanted use a different password for some reason, we’d only have one place to change it, and the rest of the system would follow along.
One of the things I’m constantly reminding myself during this process is whenever I have a problem, to step back and think about ways the Ruby language can help solve it rather than looking for some special sauce or gem to get me through the turmoil. Minitest is just Ruby — as most other gems are. Minitest generally provides enough utility to get us through the bigger use cases, but when it comes to special cases, it’s not there to hold our hand. That’s when we put our big boy pants on and make use of the language we’ve all come to know and love — Ruby!