nvim-neotest / neotest-python

MIT License
115 stars 34 forks source link

Running Neotest on a unittest folder fails when using `unittest` runner #69

Open ColinKennedy opened 3 months ago

ColinKennedy commented 3 months ago

Demo

https://github.com/nvim-neotest/neotest-python/assets/10103049/a3246a59-cf7c-48f2-99c9-aad4f9459d64

Description

Reproduction Details

Reproduction Files

(You don't need this file, it's in the tar.gz. But pasted it here so people can see

reproduction.lua ```lua -- DO NOT change the paths and don't remove the colorscheme local root = vim.fn.fnamemodify("./.repro", ":p") for _, name in ipairs({ "config", "data", "state", "cache" }) do vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name end local lazypath = root .. "/plugins/lazy.nvim" if not vim.loop.fs_stat(lazypath) then vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, }) end vim.opt.runtimepath:prepend(lazypath) local plugins = { { "nvim-neotest/neotest", config = function() require("neotest").setup{ adapters = { require("neotest-python")({ -- runner = "pytest", runner = "unittest", }) } } end, dependencies = { "antoinemadec/FixCursorHold.nvim", "nvim-lua/plenary.nvim", "nvim-treesitter/nvim-treesitter", "nvim-neotest/neotest-python", }, }, { "neovim/nvim-lspconfig", config = function() local lspconfig = require("lspconfig") local capabilities = vim.lsp.protocol.make_client_capabilities() lspconfig.jedi_language_server.setup { capabilities = capabilities } end, }, { "nvim-treesitter/nvim-treesitter", build = ":TSUpdate", config = function() require('nvim-treesitter.configs').setup{ ensure_installed = { 'python', 'query' }, } end, }, } require("lazy").setup(plugins, { root = root .. "/plugins" }) ```

Expected

Running on the tests folder should still run as expected (or, if there was a subfolder, it should also run as expected). This is working for pytest but not for unittest.

The likely reason for the failure is because the test runner isn't sourcing tests/__init__.py when Neotest runs on a directory but tests/__init__.py is sourced when you run on a file. When I need to run unittests based on a directory, I typically do python -m unittest discover --start-directory tests/ or python -m unittest discover --start-directory tests/some_subfolder/ to make sure all __init__.py files are sourced correctly. Could neotest-python be adjusted to make sure tests run consistently regardless of the test's starting point?

ColinKennedy commented 3 months ago

I believe the issue is here: https://github.com/nvim-neotest/neotest-python/blob/27a2676aa02193d6ba4ad26238c09ededa49a9a7/neotest_python/unittest.py#L39C13-L39C51

The args are parsed as ["discover", "-s", path, *args]

Which in a unittest CLI situation would be

PYTHONPATH=$PWD:$PYTHONPATH python3 -m unittest discover --start-directory tests

Which isn't enough context for the unittest. According to unittest discover's help

  -t TOP, --top-level-directory TOP
                        Top level directory of project (defaults to start
                        directory)

When -s is given but -t is not, unittest discover assumes that the given directory is the top of the project so it doesn't search __init__.py from that point.

This fixes it

PYTHONPATH=$PWD:$PYTHONPATH python3 -m unittest discover --start-directory tests --top-level-directory .

When I adapted that solution to Neotest locally...

PYTHONPATH=$PWD:$PYTHONPATH python3 {root}/neotest-python/neotest.py --runner unittest --results-file /tmp/results --stream-file /tmp/stream -- tests --top-level-directory . blahblah_case_id

Now it works