This is a neotest adapter for Google Test, a popular C++ testing library. It allows easy interactions with tests from your neovim. It should work well out-of-the-box for most cases, though some features (see below) are not yet supported.
- Neovim 0.12+ or nightly.
- Google Test 1.10+
- neotest (latest, incl. nvim-nio and plenary.nvim)
- Tree-sitter CPP parser (e.g., via nvim-treesitter's
TSInstall cpp) - nvim-dap (latest, optional, required for debugging)
The plugin provides full support of all neotest features:
- running tests inside NeoVim
- seeing pretty output
- debugging tests
- all other niceties of neotest
One major feature is not yet supported:
- Build tool integration for recompilation - you have to do that manually (or with some other plugin) for now
TEST_P, TYPED_TEST, and TYPED_TEST_P source declarations remain selectable
parents. After an executable is configured and the file is saved, the summary
shows each compiled case beneath its source declaration. Select a leaf to run or
debug its exact Google Test name, or select the parent to run every compiled case
for that declaration. Buffer-based nearest-test selection chooses the source
parent. Generated cases report their results independently; a failed case also
marks its parent failed.
The executable's --gtest_list_tests output supplies the runtime names. After
the first executable configuration, save the source file to show its compiled
cases. Later executable rebuilds refresh those cases automatically, including
when the source buffer is closed; :ConfigureGtest is only needed again to
change the executable mapping. Other generated Google Test macro families are
not yet supported.
To run each compiled case in a separate process, set process_isolation = true
in the adapter setup. This applies to normal runs; DAP runs keep their normal
debugging behavior. The default is false, so a selection runs grouped by
executable. Isolated runs start one process per case, which costs more time for
large selections but prevents process-local state and a crashed case from
affecting later cases. Each case uses an exact Google Test filter and its own
JSON report. Generated cases require a configured executable and a refreshed
runtime inventory. Rebuilding the executable refreshes that inventory after
the initial discovery.
You can override the setting for one run with
require("neotest").run.run({ process_isolation = true }).
Contributions are welcome! :)
Use your favorite package manager. Don't forget to install neotest itself, which
also has a couple dependencies. The plugin also depends on plenary.nvim, chances
are that so do your other plugins.
For debugging, you also need nvim-dap, and a debug adapter (codelldb is recommended), you can install it manually or with mason.nvim. For setting it up, see nvim-dap wiki.
-- best to add to dependencies of `neotest`:
{
"nvim-neotest/neotest",
dependencies = {
"nvim-lua/plenary.nvim",
"alfaix/neotest-gtest"
-- your other adapters here
}
}Simply add neotest-gtest to the adapters field of neotest's config:
require("neotest").setup({
adapters = {
require("neotest-gtest").setup({})
}
})Before running tests, you need to assign them to executables. For that, navigate
to the neotest summary window (neotest.summary.open()), mark the tests you want
to run (m by default), and run :ConfigureGtest in that same window. It will prompt
you to enter the path to the executable. You can set the executable path only for
parent directory, no need to set it for each test separately. This configuration
is persisted on disk.
Once that's done, use neotest the way you usually do: see
their documentation.
You don't need to call any neotest-gtest functions for ordinary usage.
neotest-gtest comes with the following defaults:
local utils = require("neotest-gtest.utils")
local lib = require("neotest.lib")
require("neotest-gtest").setup({
-- fun(string) -> string: takes a file path as string and returns its project root
-- directory
-- neotest.lib.files.match_root_pattern() is a convenient factory for these functions:
-- it returns a function that returns true if the directory contains any entries
-- with matching names
root = lib.files.match_root_pattern(
"compile_commands.json",
"compile_flags.txt",
"WORKSPACE",
".clangd",
"init.lua",
"init.vim",
"build",
".git"
),
-- which debug adapter to use? dap.adapters.<this debug_adapter> must be defined.
debug_adapter = "codelldb",
-- fun(string) -> bool: takes a file path as string and returns true if it contains
-- tests
is_test_file = function(file)
-- by default, returns true if the file stem starts with test_ or ends with _test
-- the extension must be cpp/cppm/cc/cxx/c++
end,
-- How many old test results to keep on disk (stored in stdpath('data')/neotest-gtest/runs)
history_size = 3,
-- Run one compiled case per process for normal runs (slower on large selections).
process_isolation = false,
-- To prevent large projects from freezing your computer, there's some throttling
-- for -- parsing test files. Decrease if your parsing is slow and you have a
-- monster PC.
parsing_throttle_ms = 10,
-- set configure to a normal mode key which will run :ConfigureGtest (suggested:
-- "C", nil by default)
mappings = { configure = nil },
summary_view = {
-- How long should the header be in tests short summary?
-- ________TestNamespace.TestName___________ <- this is the header
header_length = 80,
-- Your shell's colors, if the default ones don't work.
shell_palette = {
passed = "\27[32m",
skipped = "\27[33m",
failed = "\27[31m",
stop = "\27[0m",
bold = "\27[1m",
},
},
-- What extra args should ALWAYS be sent to google test?
-- if you want to send them for one given invocation only,
-- send them to `neotest.run({extra_args = ...})`
-- see :h neotest.RunArgs for details
extra_args = {},
-- see :h neotest.Config.discovery. Best to keep this as-is and set
-- per-project settings in neotest instead.
filter_dir = function(name, rel_path, root)
-- see :h neotest.Config.discovery for defaults
end,
})All contributions are welcome. If you would like to contribute, but not sure how to get started, please open an issue, and I'll do my best to help you.
Should you feel confident enough to write a PR on your own, please make sure to
include tests. The plugin is tested quite extensively, you can run make to run
the tests. Integration testsuite requires a functioning C++11 compiler, and will
download googletests as a submodule.
MIT, see LICENSE