nvim-neotest / nvim-neotest/neotest-python

fix: pytest config ignored when `python_functions` / `python_classes` / `describe_prefixes` are customised

Open
#115 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
192
Forks
60
PR merge metrics
No merged PRs in 30d

Description

pytest config ignored when python_functions / python_classes / describe_prefixes are customised

Problem

When using custom pytest naming conventions (e.g. should_*, it_* for functions or A_*, Describe* for classes), neotest-python silently ignores the project configuration and falls back to defaults. Tests with non-default prefixes are never discovered.

A secondary symptom is that on large projects the plugin hangs Neovim during test discovery.

Environment
  • neotest-python (latest)
  • pytest with custom [tool.pytest.ini_options] in pyproject.toml
  • optionally: pytest-describe plugin
Reproduction

pyproject.toml:

[tool.pytest.ini_options]
python_functions = "should_* it_* test_*"
python_classes   = "Describe*  A_* Test*"
describe_prefixes = ["describe", "context"]
def describe_math():
    def it_adds():
        assert 1 + 1 == 2          # not discovered

class DescribeMath:
    def should_multiply(self):
        assert 2 * 3 == 6          # not discovered

def test_fallback():
    assert True                    # discovered (default prefix)

Only test_fallback is discovered. Functions with it_, should_ prefixes and
classes with Describe* prefix are invisible to the plugin.

Root causes

1. Subprocess runs without cwd — reads the wrong pyproject.toml

scan_pytest_config in base.lua launches the config-extraction subprocess via
lib.process.run with no working directory. The process inherits Neovim's cwd
(which may differ from the project root), so pytest finds the wrong — or no —
pyproject.toml and returns defaults.

2. Hang on large projects

The fix attempted by passing the project root as a pytest collection path
(pytest.main(["-k", "neotest_none", root])) causes pytest to walk the entire
testpaths tree before printing the config JSON, blocking Neovim indefinitely on
large projects.

3. config.getini("describe_prefixes") crashes silently

In pytest.py, TestNameTemplateExtractor.pytest_collection_modifyitems calls
config.getini("describe_prefixes") without a try/except. When pytest-describe
is not installed this raises ValueError, crashing the subprocess before any JSON
is printed. Lua receives no output and uses hardcoded defaults.

4. Wrong fallback default for test_function_pattern

The hardcoded Lua fallback is "^test", which matches unintended names like
testing_helper or testutils and misses the it_* prefix entirely. It should
be "^test_|^it_".

5. Missing treesitter query for decorated namespace functions

Decorated test functions (@decorator\ndef test_foo()) and decorated classes are
handled, but decorated namespace/container functions are not:

@some_decorator
def describe_math():       # ← not captured as a namespace
    def it_adds(): ...
Proposed fix

neotest_python/pytest.py — replace the pytest.main() call in
extract_test_name_template with direct parsing of the config files
(pyproject.toml via tomllib/tomli, pytest.ini / setup.cfg / tox.ini
via configparser). This is instantaneous, requires no pytest collection, and
correctly reads the project config regardless of the process working directory.
Also wrap getini("describe_prefixes") in try/except ValueError.

lua/neotest-python/base.lua — pass root (already computed in
discover_positions) through treesitter_queriesscan_pytest_config → the
subprocess argument list, so the Python script receives the project root explicitly.
Fix the fallback default from "^test" to "^test_|^it_". Add a sixth treesitter
query to capture decorated namespace/container functions.

lua/neotest-python/adapter.lua — pass root to base.treesitter_queries.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in neotest_python/pytest.py at extract_test_name_template and pytest_collection_modifyitems, then trace root through lua/neotest-python/adapter.lua, base.lua, treesitter_queries, and scan_pytest_config. Verify the project configuration is read from the supplied root without collection hangs, missing pytest-describe does not suppress output, and decorated namespace functions are discovered with the stated fallback prefixes.

Written by the indexing model from the issue text.

Assessment

Tech stack
lua, python
Domain
developer-experience, testing-qa, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.