vim running Rust tests

Introduction

If you ever used VS Code to edit Rust source code, you might already know you can launch just the test you care about.

Run a Rust test in VSCode

But I love too much Vim to convert to VSCode. And yes, I know there is a Vim plugin but these emulation plugins are never complete and I always end up using vim shortcuts that doesn’t exist in the plugin. It annoys me.[1]

However, there is a bunch of nice things in VSCode like running the test you want, without running the entire suite test.

Selecting tests with cargo

First of all, let see how to run a test and only the tests you want.

If you have a lib.rs with the following test.

#[cfg(test)]
mod tests {
	use super::*;
	mod addition_tests {
		use super::*;
		#[test]
		fn add_works() {
			assert_eq!(1 + 1, 2);
		}

		#[test]
		#[should_panic]
		fn add_panics() {
			assert_ne!(1 + 1, 2);
		}
	}
}

Then you can run the add_work() test function with

cargo test --lib -- --exact tests::addition_tests::add_works

Or run all the tests in this file with

cargo test --lib -- tests::addition_tests

And it works similarly for integration tests.

cargo test --test addition

will run all the tests in tests/addition.rs and

cargo test --test addition -- --exact add_works

will only run the add_works() function in tests/addition.rs.

Let’s do it in vim

The algorithm is relatively simple. We start from the position of the cursor and try to deduce what test the user want to launch. If the cursor is inside a test function, let’s launch only this function. If the cursor is in a file that contains test, let’s launch all the tests of this file, etc.

Here is a simplified algorithm. First, we iterate over the blocks { …​ } going from the narrower block containing the cursor, to the larger block containing the cursor. During this iteration, we identify the block of the test function (function annotated with #[test]) if there is one, and all the wrapping modules. Then we can iterate on the file path to deduce the rest of the modules.

From the file path, we can also deduce if this is an integration test or not. This will help to choose between --lib or --test options.

You can find the code in my vim script here.

Conclusion

Now, you have a nice function that you can map to a shortcut. I use F6.

noremap <F6> <Esc>:call <SID>rust_execute_test()<Enter>

I will add an additional comment because we forget too often about that, vim documentation is awesome. Most of my problems in writing this script was solved through documentation. The only drawback of the documentation is to find the right section. [2]


1. I’ve had the same problem with IdeaVim in IntelliJ or with Vimium to name a few
2. As I am writing this blog post, I’m discovering the command :helpgrep which might have help me.

links

social