An introduction to vspec
Vspec is a library that allows you to test-drive your Vimscript code. In this tutorial, we’ll cover the basics: how to inspect the contents of a buffer, how to simulate the actions of a user, and how to invoke user-defined mappings.
I’ll be running my Core Vim Class online on Thursday, December 5th. Tickets cost $255, but you can get the earlybird discount of $230 if you buy yours before November 29th. The price includes an exclusive screencast that summarises the material from the class.
Vspec lets you write tests for you Vimscript code, following a format that resembles rspec. We can use a
describe block to specify a context, then wrap each individual test in an
it block. Each of these blocks is closed with an
end keyword, just like in ruby:
describe 'vspec' it 'is inspired by rspec' end end
Check out Kana Natsuno’s blog post for instructions on how to set up a Vim plugin to be tested by vspec.
Here’s the vspec code that was demonstrated in the video:
nnoremap x daw describe 'vspec' before new put! = 'Welcome to Vimcasts' end after close! end it 'can read the contents of the buffer' Expect getline(1) == "Welcome to Vimcasts" end it 'feels just like operating Vim!' normal gg$ normal daw Expect getline(1) == 'Welcome to' Expect getreg('"') == ' Vimcasts' end it 'can exercise user-defined mappings' normal gg$ normal x Expect getline(1) == 'Welcome to' Expect getreg('"') == ' Vimcasts' end end
:normal Vs :normal!
In the demo, I used the
:normal command. It’s worth noting that the
:normal! command, when used with a trailing bang, will avoid user-defined mappings. That’s useful if you want to invoke built-in functionality. For example, if we had used
:normal! x in our vspec test, then it would have invoked Vim’s built-in
x command, ignoring our custom mapping.
In Learn Vimscript the Hard Way, Steve Losh says “when writing Vim scripts you should always use normal!, and never use plain old normal”. This is good advice when writing plugin functionality, but you can disregard it when writing vspec tests for that same plugin. If you want to test the functionality of a user-defined mapping, then
:normal (without the bang) is the way to do it.