loading...
Cover image for Supercharging Vim: Instant testing

Supercharging Vim: Instant testing

mblayman profile image Matt Layman Originally published at mattlayman.com ・3 min read

How do you know that your code works?

That's a surprisingly deep question if you really dig into the meaning of "works," but from a practical level, you can trust that code works by verifying its behavior; and a good way to verify is to write test code that will assert that the code behaves as expected.

In the second post of this "Supercharging Vim" series, we're going to explore how you can run automated tests within Vim. You'll feel like you have a new superpower when you see test results appear before you instantaneously.

Not-so-instant testing

As a heavy user of Python, a dynamic programming language lacking some "guarantees" that come with statically typed languages, I write a lot of automated tests.

Automated tests give me the confidence that my code is doing what I think it's doing. For the times that the code is "misbehaving," my tests help me to narrow in on the problem.

My process for writing code and test code used to look like this:

  1. Write some test code.
  2. Switch to a different terminal and run the test runner.
  3. Switch back to Vim and write code that makes the test pass.
  4. Repeat.

I would be in that process loop all day long. Do you see the huge inefficiency in that loop? I was constantly switching terminals between writing and running code.

Switching between writing and running code comes with the territory of doing software development. I learned early in my career the benefit of running code frequently as a technique for catching errors. My process problem was not the context switch itself, but how long the switch took because of the terminal switch.

Even aided by muscle memory for changing terminal tabs or windows, I would have to find the right terminal, get the test runner command from my shell's history, and execute the runner. To make things worse, if I had to run a single test, the result would be like:

$ nosetests myproject.tests.test_widget.TestWidget:test_feature

That's a lot of work to run some tests. Shouldn't it be easier to run a single test rather than harder?

As Raymond Hettinger is prone to say: There must be a better way!

Testing inside Vim with vim-test

My former co-worker at Storybird, Ben Johnson, introduced me to a Vim plugin called vim-test. This plugin dramatically changed my relationship with automated test tools.

If you followed the first post and added vim-plug to your vimrc, then add vim-test in your plugin section:

Plug 'janko-m/vim-test'

Run :PlugInstall to install vim-test.

Now you should be ready for some magic. Open up a project, navigate to a test file, put your cursor inside a test method, and run :TestNearest.

For those of you who aren't able to follow along, Vim should have showed tests running without having to switch terminals. Even cooler than that, vim-test figures out the exact test to run so the results look similar to the myproject.tests.test_widget.TestWidget:test_feature command that I showed earlier.

After adding vim-test, I experienced an immediate boost in my productivity. I discovered that the terminal switch not only took more time, but it also negatively affected my mental flow. With vim-test, I could run a test, see it pass, and move on in the code without feeling like I left my editor. My brain got to stay focused on code, and I think this is an extremely valuable benefit.

You can take vim-test a step further by adding some custom key mappings to quickly invoke longer commands like :TestNearest, :TestFile, or :TestSuite. I use the space bar as my <Leader> key and give some mappings to <Leader>t, <Leader>f, and <Leader>s. These mappings let me run all kinds of tests in two key strokes. I think it really shows off Vim's power.

Next time

vim-test is absolutely one of the tools that made my development flow faster. In the next post, we'll focus on another flow improvement tool that does insanely fast file navigation with fuzzy finding.

Next up: ctrlp

This article first appeared on mattlayman.com.

Posted on by:

mblayman profile

Matt Layman

@mblayman

Matt Layman is a software engineer from Frederick, MD. He is an open source software maintainer and advocate for Python.

Discussion

markdown guide
 

Heya Matt -- I'm just browsing Dev.to's #vim tag and came across your post. I recently discovered vim-test, too! It's been quite the improvement, but I didn't have a terrible flow before that I thought I'd share in case you decide you no longer want that plugin dependency. You may or may not be familiar with the following...

If you don't want to use multiple tabs (which I avoid), you can background and foreground processes/jobs. ctrl-z (background Vim), run test command, $ fg (brings Vim back to the foreground). I've used this for years.

Where vim-test shines for me is testing within the same test-file with :TestNearest as I don't have to visually find the test number or name and append it as a suffix to the test command and filepath. I didn't bother memorizing the key-bindings as hitting the tab key after :test (defaults to TestFile), :testn (nearest), and :tests (suite) works well enough for me.

Lastly, the bottom of your article shows ctrlp being the next topic up. Curious about whether you're familiar with fzf. I switched away from ctrlp years ago, because it's faster, more featureful (inline/in-project search and preview when coupled with ripgrep or ag) and it's a helluva utility for command-line use. A lot of us do a combination of ls and cd before arriving at the directory containing the project or file we want to open with Vim, but with fzf, you can simply do $ vim ** (followed by a tab) and it'll begin fuzzy searching your entire file system from the current directory. The ** bash-completion globbing from fzf can be prefixed with pretty much any Unix utility, like $ cd **/$ cd foo/bar/** (to anchor the search from a specific directory). I also use $ rg --files | fzf to find a file in the current working directory that contains many files.

Happy programming!

 

Those are great thoughts, David! I've heard of fzf and gone back and forth about whether to use it or not. Ultimately, I've found a happy combination with CtrlP which works for me.

That ** technique sounds pretty cool so I'll have to give that a try in the future.

For context, I wrote this series initially in 2017 so I've had some time to think about my choices. I periodically go back and upgrade various plugins (like ag to rg) when I have a weekend to burn.