-
Hello fellow Neovimmers, I am trying to use Busted to test my plugins and I want to run each test or at least each I have set up Busted to use Neovim as its Lua interpreter. Here are all the pieces:
Nothing surprising here. Let's take it for a spin. Create two test files:
This is bad because it means Busted cannot be used for anything except the simplest of unit tests. Is there some way to get isolation working? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
I have found a solution, and it's actually quite obvious in hindsight. The key insight is that I do not need to run the tests in separate processes, but that I need to run the code I want to test in separate processes. Basically:
Here is an example: local jobopts = {
rpc = true,
width = 80,
height = 24,
}
describe('Process isolation', function()
-- This will be the channel for each test
local nvim
before_each(function()
-- Start the remote Neovim process. The `--embed` flag lets us control
-- Neovim through RPC, the `--headless` flag tells it not to wait for a
-- UI to attach and start loading plugins and configuration immediately
nvim = vim.fn.jobstart({'nvim', '--embed', '--headless'}, jobopts)
end)
after_each(function()
vim.fn.jobstop(nvim)
end)
it('Defines a global variable', function()
rpcrequest(nvim, 'nvim_set_var', 'foo', 'bar')
local foo = rpcrequest(nvim, 'nvim_get_var', 'foo')
assert.is.equal('bar', foo)
end)
it('Does not have access to previous editor state', function()
assert.has_error(function() rpcrequest(nvim, 'nvim_get_var', 'foo') end)
end)
end) And that's it, we have process isolation. It isn't pretty, but it gets the job done. We can define some helper functions to reduce the boilerplate of |
Beta Was this translation helpful? Give feedback.
-
To wrap up the topic, let's talk about configuration isolation. I do not want my own configuration and plugins to interfere with testing. On the other hand, I might want some plugins present during testing, such as nvim-treesitter for installing parsers. First we need to adjust the shim: #!/bin/sh
# Set custom XDG base directory paths to isolate the test Neovim from the
# user's own configuration and data files.
export XDG_CONFIG_HOME='test/xdg/config/'
export XDG_STATE_HOME='test/xdg/local/state/'
export XDG_DATA_HOME='test/xdg/local/share/'
# We have to explicitly enable plugins, see ':h -l'
nvim --cmd 'set loadplugins' -l $@ This is yet another reason why the XDG Base Directory Specification is far superior to dotfiles (which are actually a bug). I have set aside the directory Let's now talk about plugins. At minimum we need the current directory as a plugin, so let's add it to the standard path for plugins as a symlink. ln -s ../../../../../../../../ test/xdg/local/share/nvim/site/pack/testing/my-plugin Here Next let's add nvim-treesitter as a plugin. I am going to use Git submodules, that way we can track exactly which version we use for testing. git submodule add https://github.com/nvim-treesitter/nvim-treesitter test/xdg/local/share/nvim/site/pack/testing/start/nvim-treesitter Note that we place the submodule next to the other plugin where it can be found automatically. With this we have all pieces in place for reliable and reproducible plugin tests. Run them locally, run them remotely, run them in a CI pipeline, whatever. I hope this helps save time for whoever happens to come across it in the future. |
Beta Was this translation helpful? Give feedback.
I have found a solution, and it's actually quite obvious in hindsight. The key insight is that I do not need to run the tests in separate processes, but that I need to run the code I want to test in separate processes. Basically:
Here is an example: