This plugin provides an RSpec adapter for the Neotest framework.
Install with the package manager of your choice:
Lazy
{
"nvim-neotest/neotest",
lazy = true,
dependencies = {
...,
"olimorris/neotest-rspec",
},
config = function()
require("neotest").setup({
...,
adapters = {
require("neotest-rspec")
},
})
end
}
Packer
use({
"nvim-neotest/neotest",
requires = {
...,
"olimorris/neotest-rspec",
},
config = function()
require("neotest").setup({
...,
adapters = {
require("neotest-rspec"),
}
})
end
})
Note
You only need to the call the setup
function if you wish to change any of the defaults
Click to see the default configuration
adapters = {
require("neotest-rspec")({
rspec_cmd = function()
return vim.tbl_flatten({
"bundle",
"exec",
"rspec",
})
end,
root_files = { "Gemfile", ".rspec", ".gitignore" },
filter_dirs = { ".git", "node_modules" },
transform_spec_path = function(path)
return path
end,
results_path = function()
return async.fn.tempname()
end
}),
}
The command used to run tests can be changed via the rspec_cmd
option:
require("neotest-rspec")({
rspec_cmd = function()
return vim.tbl_flatten({
"bundle",
"exec",
"rspec",
})
end
})
One issue you can run into is when you use generated tests:
RSpec.describe SomeClass do
describe "some feature" do
FIXTURES.each do |method, path|
it "does something with the #{method} and #{path}" do
# ...
end
end
end
end
The test will show as passing if any one of the tests pass instead of if all of
them pass. You can change the test command to use --fail-fast
to fix this.
However now your other tests will all fail if even a single test fails.
To solve this you can customize your command depending on the type of test you
are running by using the optional positional argument position_type
require("neotest-rspec")({
-- Optionally your function can take a position_type which is one of:
-- - "file"
-- - "test"
-- - "dir"
rspec_cmd = function(position_type)
if position_type == "test" then
return vim.tbl_flatten({
"bundle",
"exec",
"rspec",
"--fail-fast"
})
else
return vim.tbl_flatten({
"bundle",
"exec",
"rspec",
})
end
end
})
Now when you run your tests from a single test it will fail fast and show the correct error on your generated tests. When you run the whole file it won't fail fast and a single error won't cause all your other tests to fail.
For Neotest adapters to work, they need to define a project root whereby the process of discovering tests can take place. By default, the adapter looks for a Gemfile
, .rspec
or .gitignore
file. These can be changed with:
require("neotest-rspec")({
root_files = { "README.md" }
})
You can even set root_files
with a function which returns a table:
require("neotest-rspec")({
root_files = function() return { "README.md" } end
})
By default, the adapter will search for _spec.rb
files in all dirs in the root with the exception of node_modules
and .git
. You can change this with:
require("neotest-rspec")({
filter_dirs = { "my_custom_dir" }
})
You can even set filter_dirs
with a function which returns a table:
require("neotest-rspec")({
filter_dirs = function() return { "my_custom_dir" } end
})
The following configuration overrides rspec_cmd
to run a Docker container (using docker-compose
) and overrides transform_spec_path
to pass the spec file as a relative path instead of an absolute path to RSpec. The results_path
needs to be set to a location which is available to both the container and the host.
require("neotest").setup({
adapters = {
require("neotest-rspec")({
rspec_cmd = function()
return vim.tbl_flatten({
"docker",
"compose",
"exec",
"-i",
"-w", "/app",
"-e", "RAILS_ENV=test",
"app",
"bundle",
"exec",
"rspec"
})
end,
transform_spec_path = function(path)
local prefix = require('neotest-rspec').root(path)
return string.sub(path, string.len(prefix) + 2, -1)
end,
results_path = "tmp/rspec.output"
})
}
})
Alternatively, you can accomplish this using a shell script as your RSpec command. See this comment for an example.
Important
In order for the adapter to work, your RSpec tests must end in _spec.rb
To test a single test, hover over the test and run require("neotest").run.run()
To test a file run require("neotest").run.run(vim.fn.expand("%"))
To test a directory run require("neotest").run.run("path/to/directory")
To test the full test suite run require("neotest").run.run("path/to/root_project")
e.g. require("neotest").run.run(vim.fn.getcwd())
, presuming that vim's directory is the same as the project root.
In order to enable DAP for a test or test suite, ensure that nvim-dap and nvim-dap-ruby are installed and follow the strategies docs. An example snippet can be found below.
require("neotest").run.run({ strategy = "dap" })
This will run the closest test under DAP.
This project is maintained by the Neovim Ruby community. Please raise a PR if you are interested in adding new functionality or fixing any bugs. When submitting a bug, please include an example spec that can be tested.
To trigger the tests for the adapter, run:
make test