This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
vim-easytest is a Vim plugin that simplifies running unit tests by automatically detecting test names, classes, and files at the cursor position. It integrates with vim-dispatch to run tests asynchronously or in the terminal.
plugin/easy_test.vim: Single-file plugin containing all functionality. The plugin uses a VimScript wrapper around Python code executed via pythonx. The architecture is:
- VimScript layer (lines 1-21): Plugin initialization, guards, and syntax configuration variables
- Python layer (lines 22-168): All test detection and command generation logic
The run_test() function implements the core logic:
- Syntax detection (lines 132-137): Checks
g:easytest_*_syntaxvariables to determine which test framework to use (defaults to Django) - AST navigation (lines 139-148): Uses Vim's search commands to find test function and class definitions by searching backwards for
def,fn,func(functions) andclass,mod(classes/modules) - Command generation: Delegates to framework-specific functions (lines 56-126) that construct test runner commands
- Execution (lines 164-167): Runs via vim-dispatch (
Startfor async,Dispatchfor terminal)
Each framework has a dedicated function that generates test commands:
- easytest_django_syntax (lines 56-70): Converts file paths to dotted module notation
- easytest_django_nose_syntax (lines 72-79): Uses django-nose's
:separator - easytest_pytest_syntax (lines 81-87): Uses pytest's
::separator - easytest_ruby_syntax (lines 89-98): Uses ruby's
-I,-t, and-nflags - easytest_rust_syntax (lines 100-114): Constructs
cargo testcommands with--nocapture - easytest_go_syntax (lines 116-126): Constructs
go testcommands with-runfor specific tests
The plugin supports 5 test execution levels (controlled by the level parameter):
test: Run single test function at cursorclass: Run all tests in the class at cursorfile: Run all tests in current filepackage: Run all tests in the package/moduleall: Run entire test suite
The plugin searches for function/class definitions using Vim regex (lines 140, 145):
- Function pattern:
?\<def\>\|\<fn\>\|\<func\>- matches Pythondef, Rustfn, Gofunc - Class pattern:
?\<class\>\|\<mod\>- matches Python/Rubyclass, Rustmod
After finding a match, it extracts the name by:
- Stripping
asyncprefix (line 141) - Splitting on space and taking second token (function/class name)
- Splitting on
(to remove parameters - Stripping trailing
:,{, and whitespace
Django tests require dotted module notation (lines 61-70). The plugin:
- Gets file path from
@%register (current buffer) - Removes
.pyextension and replaces/with. - For package-level tests, removes the last component using
rpartition('.')
Start: Runs command asynchronously via vim-dispatch (line 167)Dispatch: Opens terminal for interactive debugging like pdb (line 165)
Lines 129-161 preserve cursor position:
- Stores original position (line 130)
- Performs backward searches (lines 140, 145)
- Restores position after extracting names (line 161)
- Clears search highlights (line 163)
Syntax selection is controlled by global Vim variables (check one per filetype):
let g:easytest_django_syntax = 1
let g:easytest_django_nose_syntax = 1
let g:easytest_pytest_syntax = 1
let g:easytest_ruby_syntax = 1
let g:easytest_rust_syntax = 1
let g:easytest_go_syntax = 1Per-project configuration can use .vimrc in the project directory (requires set exrc and set secure in ~/.vimrc).
- vim-dispatch: Required for async test execution and terminal integration
- Python support: Vim must be compiled with Python (pythonx support)
There is no automated test suite. Manual testing workflow:
- Open a test file in Vim
- Position cursor inside a test function
- Call
:py run_current_test()or other API functions - Verify the command in the output (line 162 prints the command)
- Check test results in quickfix window (async) or terminal
To add support for a new test framework:
- Add a new
easytest_{framework}_syntax()function following the pattern of existing implementations - Add the function name to the detection loop (line 132)
- Consider language-specific patterns for finding functions/classes if needed
- Test with all granularity levels (test, class, file, package, all)
The function receives cls_name and def_name as parameters (may be None) and should return the complete shell command to run tests.