6 Lessons From a Week of Work Related to Testing in Rails

Gaelyn Cooper
4 min readNov 1, 2021

--

Photo by Scott Graham on Unsplash

I’ve recently embarked on an initiative to make one small pull request every day, with the goal of that PR being merged by the end of the day. My mentor described this strategy as a leading indicator of growth.

For the specific codebase I was working on, the natural place to start was to fill in gaps in testing. I imagine this could become a multi-part series as this project continues. The six lessons here are based off of refactors I did myself or conversation I had with other devs on my PRs.

Here are 6 lessons learned from my first week backfilling tests.

1. Why add tests in the first place?

I’ve been working through The Complete Guide to Rails Testing by Jason Swett, and he presents many arguments for why we should write tests at all.

I won’t spell out all the reasons here, but highlight the one that resonated with me the most as a junior dev. Having well written tests makes it so much easier to understand the code and flow of the application, and can quickly give someone with no context the ability to jump in and fix bugs or write new features.

After writing a few tests I feel much better acquainted with how the app works than if I just jumped in and tried to start debugging or adding a feature blindly. In fact, I was recently working on a bug fix and there was some data that was really nested and I had a lot of trouble figuring out what it was supposed to look like and why we were getting the error. I did a little digging around and found a model test that gave me the setup I needed and that saved me an incredible amount of time and mental energy versus trying to come up with that setup on my own.

2. Write clearly labeled test names

I was taught test-driven development at the bootcamp I attended, but when you’re doing a lot of solo projects or pair-programming as I did, you may find yourself falling into the habit of writing “you know what I mean” test names.

For me they ended up looking something like this:

If I was looking at this test with no context about what the sort_by_date method actually does, I'd have to go to the method itself and parse through the code to figure it out. Whereas if I had a better test name I would know exactly what the method was doing.

3. Be descriptive in your variable names

This is another lazy tester trap that I’ve fallen into many times that’s closely related to #2. If you’re making several instances of an object with various attributes that need to be tested, it’s helpful to use variable names that will make sense to other developers reviewing your code.

Not helpful:

More helpful:

This may not be the best example, but you can generally see why I might assert inclusion of user_1_incomplete_past_due_task if I was testing a method that returns all Tasks not completed before the due date. If I wanted to know which users have active tasks, you could understand why I might refute inclusion of user_with_no_tasks.

4. Don’t forget to test all components

There’s two parts to this one.

a) If you’re trying to test a method that has 4 valid statuses, and you only test 2 of them, that’s an incomplete test. Test every possibility. Raise your hand if you’re guilty. 🙋🏻‍♀️

b) Don’t forget to include some instances that should not be included in addition to the ones that should be included. Otherwise how do you know your method isn’t returning things that it shouldn’t?

5. Keep your setup minimal

In other words, don’t add unnecessary instances/relationships to your setup. I mistakenly added a join connecting two instances that had no bearing on my test. I had made an assumption that I needed it. This only serves to clutter and slow down your tests. Start with what you know is needed and let your tests fail and guide you.

On a related note, I had a much more experienced developer recommend that I not use a def setup or before :each, but rather include only what's needed for each individual test. The reason being that it gets confusing quickly and problems can arise when you need different instances with unique attributes for different tests.

6. Don’t overdo the assertions

This may seem obvious, but it’s really not necessary to write every assertion/expectation you can think of. I realized this after I had done something similar to this:

That refute is completely unnecessary, right? I've asserted that expected_array == actual_array which would have failed if any other tasks were included.

--

--

No responses yet