Faster TDD feedback with tmux, tslime.vim, and turbux.vim
tl;dr Developing in a tmux session has sped up my TDD cycle
considerably, especially with the help of tslime.vim and turbux.vim. I
get immediate feedback in one pane, but never have to leave vim or lose
context of what I'm working on to see the test result.
Taking a cue from Xavier Shay's excellent intro to tmux, I've
been using tmux lately as my primary workspace. There are excellent
introductions to tmux elsewhere, but I've really
enjoyed the switch from MacVim/Terminal to a single tmux session for
development. But rather than sing tmux's praises, I'd like to talk about
how tmux and a vim plugin have changed my testing feedback loop for the
Other test-running solutions
Autotesting gives you immediate feedback, but runs everytime you save a
file. Even though this often is desired behavior, I can't tell you how
many times I've saved a feature file, only to immediately notice a typo.
Especially with Rails project, this can be an expensive amount of time.
I end up feeling punished for saving my work.
I've also tried more editor-embedding techniques of running tests. Both
rails.vim and rake.vim provide facilities for running
combined with a keyboard shortcut, this gets closer to the kind of
control I like to have, running my tests exactly when I want them. The
downside, though, is that I lose control of my editor and have to wait
for the command to finish before I can type, or even navigate again. And
I can't look at a failure message and my code at the same time.
A faster feedback loop
A practice that is quickly gaining popularity in the Ruby community is
isolating your business logic from your persistance logic and framework.
Rather than load Rails (or some other large library or framework),
you sequester all business logic in its own class or module, and then
test that class or module in isolation. This has a ton of benefits for
the longevity of your code, but one of the side benefits is the speed
increase for running individual specs or tests. This technique is being
championed by Gary Bernhardt and Corey Haines, among others.
Because tmux is so scriptable, it isn't hard to send commands to other
panes in a tmux session programmatically. Leveraging the power of
rails.vim and tslime.vim, I've created a vim plugin that shortens
the feedback loop when practicing TDD in a tmux session. It's called
My typical workflow now involves setting up a tmux session for my
project, splitting vertically (
<C-b> %), and using layout 4 (
<Alt-4>). In fullscreen, the result is about 30% for my shell on the
left, and 70% for vim on the right.
The first time you use it, tslime.vim will prompt you to input your tmux
session name, window number, and pane number. There is completion for
each of these prompts, so you can happily mash
The plugin exposes a general-purpose function to send arbitrary text to
the configured tmux pane. For example, you can use it in the following way:
:call Send_to_Tmux("rspec ".expand("%")."\n")
The above command would send
rspec path/to/spec.rb to the configured
pane. For me, this pattern of running the test file that is currently
open is so common that I've packaged up some useful defaults in
Turbux.vim tries to intelligently choose the right spec, test or feature
to run when you invoke it. If you're in a spec, invoking the plugin
(by default with
<leader>t) will run
rspec path/to/my_spec.rb in
the corresponding pane. In a test-unit file, it will run
path/to/test.rb. In a cucumber feature file, it will run
Thanks to rails.vim's awesomeness, I've also provided some mappings for
when the current file has a corresponding test or spec. For example,
When I'm in a file that has a corresponding spec, such as a model or
controller, the command will run the that spec.
Finally, if the plugin is invoked outside the context of any feature
or spec-related file, it will simply run the most recent test command
Also, I've added a mapping for
<leader>T to run a more focused spec or
cucumber scenario. It works by adding the vim cursor's line number to
the rspec or cucumber command.
This setup has been really rewarding so far. There's far less context
switching, as I never have to leave my editor. There are also fewer
surprises. As far as I'm concerned, the faster my feedback, the better.
Note: You will probably want to use my fork of tslime.vim, as the main
repository has some outstanding bugs, and the fixes have yet to been
See the plugin in action. If the video is hard to see, visit vimeo. There is a link to download at full size.