A simple test runner for .NET projects that lets you run selected tests using predefined filters.
Example for xUnit, where you can define a Trait to categorize your tests:
using Xunit;
[Fact]
[Trait("Category", "Integration")]
public void SampleTest()
{
Assert.True(true);
}To run only tests with this trait, you would typically execute:
-
VS Test:
dotnet test --filter "Category=Integration" -
MTP:
dotnet test --treenode-filter /*/*/*/*[Category=Integration]
This plugin simplifies the process by allowing you to predefine reusable filters that can later be selected interactively.
Failed tests are automatically inserted into the Neovim quickfix list and displayed via trouble.nvim, making it easy to locate and fix them.
It integrates with:
trouble.nvimfor displaying failed tests in the quickfix list
{
"sebastianstudniczek/dotnet-test-traitor.nvim",
ft = "cs",
dependencies = {
"folke/trouble.nvim"
},
--- @type dotnet-test-traitor.Configuration
opts = {
-- define your own filters
filters = {
{
name = "Unit Tests",
value = "Category!=Manual&Category!=E2E&Category!=Integration&Category!=Performance&Category!=Service|Type=Service-InMemory",
is_vstest = true
},
{ name = "Integration", value = "Category=Integration" },
{ name = "E2E Tests", value = "Category=E2E" },
},
},
keys = {
{ "<leader>tc", "<Plug>(DotnetTestTraitorRun)", mode = "n", desc = "Run Test Category (Dotnet)" },
},
},You can define your own filters in the configuration under the opts.filters field.
Each filter has a name (used for display) and a value — a filter expression passed to the dotnet test --filter command.
Important
By default filter assumes using MTP syntax (--treenode-filter)
It's possible to invoke test execution from outside nvim. For example from git hook.
To store neovim address you can use autocmd like this:
local function write_server_file()
local server = vim.v.servername
if server == "" then
return
end
local root = vim.fs.root(0, ".git")
if not root then
return
end
vim.fn.writefile({ server }, root .. "/.nvim.server")
end
vim.api.nvim_create_autocmd("VimEnter", {
callback = write_server_file,
})and later invoke it via:
if [ -f .nvim.server ]; then
FILTER="/*/*/*/*[Category!=Service]"
RESULT_FILE=$(mktemp)
trap 'rm -f "$RESULT_FILE"' EXIT
nvim --headless --server "$SERVER" --remote-expr "v:lua.require('dotnet-test-traitor.run')({ 'value': '$FILTER' }, '$RESULT_FILE')" > /dev/null
while [ ! -s "$RESULT_FILE" ]; do
sleep 0.2
done
EXIT_CODE=$(cat "$RESULT_FILE")
exit "$EXIT_CODE"
fi