A comprehensive Emacs package for running Go tests with intelligent Treesitter support, featuring advanced navigation, subtest detection, and seamless integration with your Go development workflow.
- Introduction
- Features
- Installation
- Setup
- Usage
- Commands
- Keybindings
- Configuration
- Integration
- Examples
- Troubleshooting
- Contributing
- Authors
This Emacs package provides intelligent Go test running capabilities using Treesitter for accurate syntax parsing. It automatically detects test functions and table-driven subtests, offering a seamless "Do What I Mean" experience for Go developers.
Whether you're working with simple test functions or complex table-driven tests with nested structures, gotest-ts intelligently determines what test to run based on your cursor position.
- Smart Test Detection: Automatically detects test functions and table-driven subtests using Treesitter
- DWIM Test Execution: Run the right test based on cursor position - function or specific subtest
- Nested Structure Support: Handles complex nested structures in table-driven tests
- Tree-sitter Powered: Reliable syntax parsing that understands Go code structure
- Subtest Navigation: Jump between subtests with
next-subtestandprev-subtest - Imenu Integration: Quick navigation to any test or subtest via
imenu - Test Information: Display current test context and subtest details
- Position Awareness: Always know where you are in your test suite
You need to have Go mode configured to use Treesitter. See this Article for setup information.
(use-package gotest-ts
:ensure t
:hook (go-ts-mode . gotest-ts-setup))Clone the repository and add it to your load-path:
git clone https://github.com/chmouel/gotest-ts.el.git(add-to-list 'load-path "/path/to/gotest-ts.el")
(require 'gotest-ts)(require 'gotest-ts)
;; Complete setup with keybindings and imenu
(add-hook 'go-ts-mode-hook #'gotest-ts-setup);; Keybindings only
(add-hook 'go-ts-mode-hook #'gotest-ts-setup-keybindings)
;; Imenu integration only
(add-hook 'go-ts-mode-hook #'gotest-ts-imenu-setup)- Position your cursor in a test function or subtest case
- Run the test with
C-c t r(gotest-ts-run-dwim) - Navigate between tests using
C-c t n/porC-c t m(imenu)
The package intelligently determines what to run:
func TestProcessStatus(t *testing.T) {
tests := []struct {
name string
wantClient bool
args args{
statusOpts: provider.StatusOpts{
Status: "in_progress",
},
}
}{
{
name: "skip in progress", // ← Cursor here = runs this subtest
wantClient: true,
// ...
},
}
// ← Cursor here = runs entire function
}Sequential Navigation:
gotest-ts-next-subtest- Jump to next subtest (with wraparound)gotest-ts-prev-subtest- Jump to previous subtest (with wraparound)
Overview Navigation:
gotest-ts-imenu-goto- Open imenu with all tests and subtests- Standard
imenu- Lists all tests in format:TestName::subtest_name
| Command | Description |
|---|---|
gotest-ts-run-dwim |
Main command: Run test or subtest at point |
gotest-ts-run-function |
Run entire test function (ignore subtests) |
gotest-ts-next-subtest |
Navigate to next subtest |
gotest-ts-prev-subtest |
Navigate to previous subtest |
gotest-ts-show-test-info |
Show current test context information |
gotest-ts-imenu-goto |
Open imenu for test navigation |
gotest-ts-setup |
Complete setup (keybindings + imenu) |
gotest-ts-setup-keybindings |
Setup keybindings only |
gotest-ts-imenu-setup |
Setup imenu integration only |
Default keybindings when using gotest-ts-setup-keybindings:
| Key | Command | Description |
|---|---|---|
C-c t r |
gotest-ts-run-dwim |
Run test/subtest at point |
C-c t f |
gotest-ts-run-function |
Run entire test function |
C-c t n |
gotest-ts-next-subtest |
Next subtest |
C-c t p |
gotest-ts-prev-subtest |
Previous subtest |
C-c t m |
gotest-ts-imenu-goto |
Open test navigation menu |
C-c t i |
gotest-ts-show-test-info |
Show test info |
;; Customize the subtest field name (default: "name")
(setq gotest-ts-subtest-field-name "description")
;; Disable Go mode requirement (default: t)
(setq gotest-ts-require-go-mode nil)The package supports any subtest field name:
// With default "name" field
{name: "test case", input: 1, want: 2}
// With custom "description" field
{description: "test case", input: 1, want: 2}
// Configure: (setq gotest-ts-subtest-field-name "description")Ivy/Counsel:
(global-set-key (kbd "C-c t m") #'counsel-imenu)Helm:
(global-set-key (kbd "C-c t m") #'helm-imenu)Vertico:
Works automatically with standard imenu.
(use-package imenu-list
:config
(add-hook 'go-ts-mode-hook #'gotest-ts-imenu-setup))
;; Toggle sidebar: M-x imenu-list-smart-toggleEnhanced Dape integration with the new function name:
(defun my-dape-go-test-at-point ()
(interactive)
(dape (dape--config-eval-1
`(modes (go-ts-mode)
ensure dape-ensure-command
fn dape-config-autoport
command "dlv"
command-args ("dap" "--listen" "127.0.0.1::autoport")
command-cwd dape-cwd-fn
port :autoport
:type "debug"
:request "launch"
:mode "test"
:cwd dape-cwd-fn
:program (lambda () (concat "./" (file-relative-name default-directory (funcall dape-cwd-fn))))
:args (lambda ()
(when-let* ((test-name (gotest-ts--build-test-pattern)))
(if test-name `["-test.run" ,test-name]
(error "No test selected"))))))))After setup, M-x imenu shows:
TestProcessData
TestProcessData::valid_input
TestProcessData::invalid_input_with_spaces
TestComplexScenario
TestComplexScenario::complex_case
TestAnotherFunction
"Tree-sitter is not available"
- Ensure you're using Emacs 29+ with tree-sitter support
- Install Go language support:
M-x treesit-install-language-grammar RET go
"Not inside a test function"
- Ensure your function name starts with
Test - Check you're in a Go test file (
*_test.go)
Subtest not detected
- Verify your field name matches
gotest-ts-subtest-field-name - Ensure you're positioned within the correct struct literal
Imenu not working
- Run
M-x gotest-ts-imenu-setupmanually - Check that imenu is properly configured in your Emacs
Use gotest-ts-show-test-info to see what the package detects:
- Shows current test function
- Displays subtest name if detected
- Indicates if you're not in a valid context
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Submit a pull request
When reporting bugs, please include:
- Emacs version and tree-sitter availability
- Go mode configuration
- Sample Go test code that reproduces the issue
- Error messages or unexpected behavior
This package builds upon the excellent gotest package, adding intelligent tree-sitter integration and enhanced navigation capabilities.
- Fediverse - @chmouel@chmouel.com
- Twitter - @chmouel
- Blog - https://blog.chmouel.com