Optimize Your TDD Workflow by Writing Vim Plugins

TDD and Vim

We often spend time optimizing our workflow. We learn new technologies, new patterns and constantly improve ourselves. But we often forget about our existing tools and how powerful they are. Vim is one of those tools.

In this article we are going to build a simple Vim plugin, which creates related files. The point is not to teach you some Vim script, but to remind you that your Vim is there and it takes only a few minutes to make it better by writing a few lines of code.

The idea

The idea of our brand new Vim plugin is to help us with our TDD workflow. Every time when you create a new file, instead of creating the test file manually, Vim will magically add it for you. This approach is heavily inspired from the vim-rails plugin, which gives you a simple :A command that opens the related test file.

Before we begin

Since we are Rails developers and we use Rspec a lot, we will create our plugin with them in mind. But don’t worry, you can use it for your favourite language/framework and testing library with just a few tweaks here and there.

Here is a typical Ruby on Rails structure. We need to analyze it before starting with our code:

1
2
3
4
5
6
app/models/user.rb
app/controllers/users_controller.rb
...
spec/models/user_spec.rb
spec/controllers/users_controller_spec.rb
...

So, if we replace “app” with “spec” and “.rb” with “_spec.rb”, then we will get the path of the test file. Hm, that looks easy. But we also have to keep in mind that the file might be already created.

Create related file

Create a new file in your ~/.vim/plugin/ directory with the name related.vim.

All we need to do is grab the filename, figure out if it’s a test file or not and, depending on the result, open/create the associated file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
" Open/Create related spec/file
function! s:CreateRelated()
  let related = s:GetRelatedFile(expand('%'))
  call s:Open(related)
endfunction

" Return the related filename
function! s:GetRelatedFile(file)
  if match(a:file, '_spec\.rb$') != -1
    return substitute(substitute(a:file, "_spec.rb$", ".rb", ""), '^spec/', 'app/', '')
  else
    return substitute(substitute(a:file, ".rb$", "_spec.rb", ""), '^app/', 'spec/', '')
  endif
endfunction

" Open the related file in a vsplit
function! s:Open(file)
  exec('vsplit ' . a:file)
endfunction

" Register a new command `AC` for open/create a related file
command! AC :call <SID>CreateRelated()

You can notice that the new file is opened in a vertical split. This is our preferred workflow, but you can change it by replacing vsplit with split etc.

What’s next?

It feels good, doesn’t it? We are saving ourselves a few second each time when we create a new test file. We’ve learned some Vimscript, as well. If you want to dig deeper, we have some useful resources for you:

Conclusion

Hacking Vim scripts is easy and totally worth your time. Don’t forget - Vim is probably your greatest tool. It won’t let you down. Spend some time with your Vim files once in a while. Do some crazy experiments, solve some impossible tasks. Don’t worry if it feels like it’s out of your comfort zone. You will become better in time.

What’s your favorite Vim hack? How often do you update your vimrc? Have you learned Vimscript already? What’s your best advice when it comes to writing plugins? Share it with us.

About the author

Veselin Todorov is a software consultant focused on testing, code quality and building awesome products. He is helping companies to ship their products with confidence and style.

If you are passionate about JavaScript, Node.js, TDD, building and growing applications, you should visit his blog at RobustJS.com