The joy of creating your own toolkit
Tags: rspec, spring, neovim
Published: 2024-02-12 15:22:23

Are you a Ruby developer? You use Neovim? Then this article is for you. Although the Neovim component is not a hard requirement.

A while ago (almost two years), tired of switching between [Kitty](https://sw.kovidgoyal.net/kitty/) windows and inspired by [Tj's excellent tutorial](https://www.youtube.com/watch?v=cf72gMBrsI0) on how easy it can be to add custom features to Neovim, I wrote a [teeny tiny plugin](https://github.com/melopilosyan/rspec-integrated.nvim) to run [RSpec](https://rspec.info/) tests from within [Neovim](https://neovim.io/).

It was so much fun figuring out the weirdness of the Lua language that I just loved it. If I didn't know Ruby, I'd agree to program in Lua for full time. And the Neovim aspect only added satisfaction. I felt how the buffers, text lines and words come to life, gain character and preferences after every API discovery.

Spending years in programming I worked on different kinds of projects, tackled fresh ideas, wrote automation scripts for bizarre use cases, but this project was different. I spent so much time in IDEs that file tabs were just openings, means of entry, nothing that I could relate to. And the source code... I have long ceased to see it as [“plain” text](https://www.youtube.com/watch?v=gd5uJ7Nlvvo). Parameters, variables, methods, conditions and expressions, loops and statements, it's all conceptual, intangible.

Now my script runs underneath that text and the result reflects on top of it, treating lines and words as individual entities. The same kind of text developed in one window does something to a text in another. It was unusual, strange and exciting.

Unsurprisingly, this plugin was even more fun to use.

You hit a couple of keys, and watch the thing to test your test assumptions. Sometimes your fingers are still on the keyboard, you still think if that's enough of a test to validate your application code, when the result comes back. A nice green success message on top right corner of your screen or a little "Failure" label at the end of the line where something requires your attention.

Soon it was hard to tell what I enjoyed most was writing tests or running them. I've made myself a small toy.

---

I was happily playing with it for months. Then there was a no-ruby-coding period. And when I came back again, that fast feedback loop didn't seem that fast anymore. Even simplest test examples took 2 to 3 seconds to complete. While RSpec reported tests duration of around 0.3 seconds, the actual command didn't fall below 2.5.

![Screenshot of RSpec's output running without spring where tests took 0.29, files loaded in 1.76 and the entire command completed in 2.85 seconds](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bvi62tclv8mwgnd69pl6.jpg)
<figcaption>RSpec's runtime without Spring</figcaption>

"Files took 1.76 seconds to load". This refers to the loading of the Rails framework and the application code involved.

The application I'm using here includes the [Spring gem](https://github.com/rails/spring). Opening the Rails console, for example, uses the application running in the background, which is what Spring does. It is fast. A lot less than 2 seconds, at least. But the `bundle exec rspec` command that my plugin used has no idea about Spring.

How I didn't notice this back then is a good question. But from the other hand, 2-3 seconds is not that much. I used to run tests during active development that took minutes. Definitely can wait 2 seconds. Or so I thought, until it started to irritate me.

It turns out Spring has no native support for the `rspec` command. And yet, as is usually the case, there is this gem: [spring-commands-rspec](https://github.com/jonleighton/spring-commands-rspec).

So I installed it, generated the `bin/rspec` binstub. Here is the effect.

![Screenshot of RSpec's output running with spring where tests took 0.4, files loaded in 0.17 and the entire command finished in 0.96 seconds](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7a9sn5na2odmal4hxxyw.jpg)
<figcaption>RSpec's runtime with Spring</figcaption>

Total runtime of 2.8 seconds vs 0.9, almost 3 times faster. Impressive!

Of course, this doesn't mean that Spring will make the whole test suite 3 times faster. The 1-2 seconds difference in loading files disappears within minutes of running the entire test suite. But in the case of running single test examples or individual files over and over during development, it actually can be 2 to 3 times faster.

---

I updated my plugin to be a wee bit smarter about selecting which command to run RSpec as, and back to happy mode again.

In the end, here are a couple of facts about the `spring-commands-rspec` gem.
[It's minuscule](https://github.com/jonleighton/spring-commands-rspec/blob/master/lib/spring/commands/rspec.rb). So small it's hard to call it a gem.

1 class with 4 methods with a total of 5 lines of executable code and 2 more lines integrating with Spring. That's it. That's the whole gem.

But wait. There is more. [This code](https://github.com/jonleighton/spring-commands-rspec) was last updated ten years ago.

![Screenshot of the Github page of spring-commands-rspec gem, showing its updated ten years ago](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ucq78t5d05f624rzc5z.jpg)
<figcaption>Github page of the spring-commands-rspec gem</figcaption>

Isn't that fascinating? When was the last time you loaded a ten year old library and it still worked?

What a great example of the benefits of robust interfaces. Well done Spring!