LunarVim Debugging & Testing Python Code
This article is a follow-up article to LunarVim as a Python IDE. In this article, we will explore how to set up debugging and testing.
We will be installing and configuring various plugins to provide a streamlined debugging and testing experience.
You can find the complete final config at this GitHub repo.
Install Plugins
We will be installing three plugins to get started:
nvim-dap-python: provides default configurations for Python and methods to debug individual test methods or classes.nvim-neotest/neotest: A framework for interacting with tests within NeoVim.nvim-neotest/neotest-python: Neotest adapter for Python. Supports Pytest andunittesttest files.
You can add the plugins to your LunarVim config file like this:
lvim.plugins = {
"mfussenegger/nvim-dap-python",
"nvim-neotest/neotest",
"nvim-neotest/neotest-python",
}Setup Debug Adapter
LunarVim already includes two plugins for enabling dap and a rich visual experience using, nvim-dap, and nvim-dap-ui. So you just need to enable dap and setup your debug adapter.
In this case, we’ll be setting up debugpy as our adapter.
lvim.builtin.dap.active = true
local mason_path = vim.fn.glob(vim.fn.stdpath "data" .. "/mason/")
pcall(function()
require("dap-python").setup(mason_path .. "packages/debugpy/venv/bin/python")
end)We will also need to install debugpy, luckily Mason makes this a very easy task. Just enter, press 3 to go to the debug adapter section, and press i on debugpy.
Setup Testing Support with Neotest
We’ll be using Neotest for running our tests. With Neotest we’ll be able to do things like run individual tests, get visual feedback about the status of our tests, and more.
For this example, we’ll be using pytest as our test runner.
require("neotest").setup({
adapters = {
require("neotest-python")({
dap = {
justMyCode = false,
console = "integratedTerminal",
},
args = { "--log-level", "DEBUG", "--quiet" },
runner = "pytest",
})
}
})For more configuration options check out this link.
Set up Keybindings
This section might look a little complicated but all we’re doing is adding some keybindings to our leader key menu that pops up when you press space. For instance, pressing space d m will test the nearest method.
lvim.builtin.which_key.mappings["dm"] = { "<cmd>lua require('neotest').run.run()<cr>",
"Test Method" }
lvim.builtin.which_key.mappings["dM"] = { "<cmd>lua require('neotest').run.run({strategy = 'dap'})<cr>",
"Test Method DAP" }
lvim.builtin.which_key.mappings["df"] = {
"<cmd>lua require('neotest').run.run({vim.fn.expand('%')})<cr>", "Test Class" }
lvim.builtin.which_key.mappings["dF"] = {
"<cmd>lua require('neotest').run.run({vim.fn.expand('%'), strategy = 'dap'})<cr>", "Test Class DAP" }
lvim.builtin.which_key.mappings["dS"] = { "<cmd>lua require('neotest').summary.toggle()<cr>", "Test Summary" }Keybindings explanation:
space d m: runs the nearest testspace d M: runs the nearest test in debug modespace d f: runs all tests in filespace d F: runs all tests in file in debug modespace d S: displays summary for tests
Setting up our tests
Now we’re ready to start debugging and testing some Python code.
Get chris@machine’s stories in your inbox
Join Medium for free to get updates from this writer.
To get started clone the following repo containing some example Python code with pytest unit tests:
git clone https://github.com/ChristianChiarulli/pytest_example.git
cd pytest_exampleNow we’ll need to install pytest. Use whatever virtual environment manager you want. I’ll be using conda.
conda create -n pytest python -y
conda activate pytest
conda install - file requirements.txtBefore we get started debugging with LunarVim, let’s make sure all of the tests pass by running:
pytest tests/You should see some indication that all of the tests have run and were successful.
=========================================== test session starts ===========================================
platform darwin - Python 3.11.3, pytest-7.3.1, pluggy-1.0.0
rootdir: /Users/chris/Repos/pytest_example
collected 5 items
tests/test_calculator.py ….. [100%]
============================================ 5 passed in 0.01s ============================================Testing with LunarVim
Now we’re ready to start testing with LunarVim. To get started open the test_calculator.py file.
lvim tests/test_calculator.pyHover over a unit test and press space d m. This should test the nearest method.
To run all of the tests at once you can press space d f. You should notice little green check marks next to each test indicating they all passed.
To see a summary of all of the unit tests and the status for each test you can press space d S.
Debugging Tests
Now try adding a breakpoint to one of the tests with space d t. A little red bug should show up next to the line where you added the breakpoint.
You can now try running the test in debug mode with space d M. You should notice that the test has paused at your breakpoint and will continue after you press space d c to continue. You should also notice that some UI elements were added as well showing scopes, breakpoints, stacks, watches, debug controls, and terminal output.
You can view all of the commands for debugging by pressing space d and waiting for 1 second for the menu to show up.
Conclusion
Throughout this article, we have explored how to set up debugging and testing for Python using LunarVim.
We have installed and configured various plugins, set up the debug adapter, and configured Neotest for running tests. We have also demonstrated how to set up keybindings and debug tests using LunarVim.
With these tools at your disposal, you can now focus on writing high-quality, bug-free code and ensure that your Python projects run smoothly and efficiently.
Note: if you want to take a deeper dive into what the debug adapter protocol is checkout this article.










