| Crates.io | pytest-language-server |
| lib.rs | pytest-language-server |
| version | 0.18.0 |
| created_at | 2025-11-14 18:32:13.927298+00 |
| updated_at | 2026-01-17 15:01:06.847409+00 |
| description | A blazingly fast Language Server Protocol implementation for pytest |
| homepage | |
| repository | https://github.com/bellini666/pytest-language-server |
| max_upload_size | |
| id | 1933263 |
| size | 4,020,905 |
A blazingly fast Language Server Protocol (LSP) implementation for pytest, built with Rust, with full support for fixture discovery, go to definition, code completion, find references, hover documentation, diagnostics, and more!
Built with AI, maintained with care 🤖
This project was built with the help of AI coding agents, but carefully reviewed to ensure correctness, reliability, security and performance. If you find any issues, please open an issue or submit a pull request!
Jump directly to fixture definitions from anywhere they're used:
conftest.py filesJump to the yield statement in generator fixtures:
yield produces the fixture valueExample:
@pytest.fixture
def database():
conn = connect()
yield conn # <-- Go to Implementation jumps here
conn.close() # Teardown code after yield
Explore fixture dependencies with Call Hierarchy support:
@pytest.fixture
def database(): # <-- Call Hierarchy shows:
... # Incoming: test_query, test_insert (tests using this)
# Outgoing: connection (fixtures this depends on)
Smart auto-completion for pytest fixtures:
Find all usages of a fixture across your entire test suite:
View fixture information on hover:
Navigate fixtures within a file using the document outline:
Search for fixtures across your entire workspace:
See fixture usage counts directly in your editor:
See fixture return types inline without leaving your code:
db: Database)Generator[T, None, None] annotationsExample:
# With a fixture defined as:
@pytest.fixture
def database() -> Database:
return Database()
# In your test, you'll see:
def test_example(database): # Shows ": Database" after "database"
pass
One-click fixes for common pytest issues:
CodeActionKind::QUICKFIXDetect and fix common pytest fixture issues with intelligent code actions:
Fixture Scope Validation:
session-scoped fixture cannot depend on a function-scoped fixtureCircular Dependency Detection:
Scope mismatch example:
# ⚠️ Scope mismatch! session-scoped fixture depends on function-scoped
@pytest.fixture(scope="session")
def shared_db(temp_dir): # temp_dir is function-scoped
return Database(temp_dir)
@pytest.fixture # Default is function scope
def temp_dir(tmp_path):
return tmp_path / "test"
Undeclared Fixture Detection:
self, request) and actual local variablesOne-Click Quick Fixes:
Example:
@pytest.fixture
def user_db():
return Database()
def test_user(user_db): # ✅ user_db properly declared
user = user_db.get_user(1)
assert user.name == "Alice"
def test_broken(): # ⚠️ Warning: 'user_db' used but not declared
user = user_db.get_user(1) # 💡 Quick fix: Add 'user_db' fixture parameter
assert user.name == "Alice"
How to use quick fixes:
Built with Rust for maximum performance:
Choose your preferred installation method:
The easiest way to install for Python projects:
# Using uv (recommended)
uv tool install pytest-language-server
# Or with pip
pip install pytest-language-server
# Or with pipx (isolated environment)
pipx install pytest-language-server
Install via Homebrew for system-wide availability:
brew install bellini666/tap/pytest-language-server
To add the tap first:
brew tap bellini666/tap https://github.com/bellini666/pytest-language-server
brew install pytest-language-server
Install from crates.io if you have Rust installed:
cargo install pytest-language-server
Download pre-built binaries from the GitHub Releases page.
Available for:
Build from source for development or customization:
git clone https://github.com/bellini666/pytest-language-server
cd pytest-language-server
cargo build --release
The binary will be at target/release/pytest-language-server.
Add this to your config:
vim.lsp.config('pytest_lsp', {
cmd = { 'pytest-language-server' },
filetypes = { 'python' },
root_markers = { 'pyproject.toml', 'setup.py', 'setup.cfg', 'pytest.ini', '.git' },
})
vim.lsp.enable('pytest_lsp')
Install from the Zed Extensions Marketplace:
The extension downloads platform-specific binaries from GitHub Releases. If you prefer to use your own installation (via pip, cargo, or brew), place pytest-language-server in your PATH.
After installing the extension, you need to enable the language server for Python files. Add the following to your Zed settings.json:
{
"languages": {
"Python": {
"language_servers": ["pyright", "pytest-language-server", "..."]
}
}
}
The extension includes pre-built binaries - no separate installation required!
Install from the Visual Studio Marketplace:
Works out of the box with zero configuration!
The plugin includes pre-built binaries - no separate installation required!
Install from the JetBrains Marketplace:
Requires PyCharm 2024.2+ or IntelliJ IDEA 2024.2+ with Python plugin.
Any editor with LSP support can use pytest-language-server. Configure it to run the pytest-language-server command.
Configure pytest-language-server via your project's pyproject.toml:
[tool.pytest-language-server]
# Glob patterns for files/directories to exclude from scanning
exclude = ["build/**", "dist/**", ".tox/**"]
# Disable specific diagnostics
# Valid codes: "undeclared-fixture", "scope-mismatch", "circular-dependency"
disabled_diagnostics = ["undeclared-fixture"]
# Additional directories to scan for fixtures (planned feature)
fixture_paths = ["fixtures/", "shared/fixtures/"]
# Third-party plugins to skip when scanning venv (planned feature)
skip_plugins = ["pytest-xdist"]
Available Options:
| Option | Type | Description |
|---|---|---|
exclude |
string[] |
Glob patterns for paths to exclude from workspace scanning |
disabled_diagnostics |
string[] |
Diagnostic codes to suppress |
fixture_paths |
string[] |
Additional fixture directories (planned) |
skip_plugins |
string[] |
Third-party plugins to skip (planned) |
Diagnostic Codes:
undeclared-fixture - Fixture used in function body but not declared as parameterscope-mismatch - Broader-scoped fixture depends on narrower-scoped fixturecircular-dependency - Circular fixture dependency detectedControl log verbosity with the RUST_LOG environment variable:
# Minimal logging (default)
RUST_LOG=warn pytest-language-server
# Info level
RUST_LOG=info pytest-language-server
# Debug level (verbose)
RUST_LOG=debug pytest-language-server
# Trace level (very verbose)
RUST_LOG=trace pytest-language-server
Logs are written to stderr, so they won't interfere with LSP communication.
The server automatically detects your Python virtual environment:
.venv/, venv/, or env/ in your project root$VIRTUAL_ENV environment variableCode actions are automatically available on diagnostic warnings. If code actions don't appear in your editor:
RUST_LOG=info to see if actions are being createdIn addition to the LSP server mode, pytest-language-server provides useful command-line tools:
View all fixtures in your test suite with a hierarchical tree view:
# List all fixtures
pytest-language-server fixtures list tests/
# Skip unused fixtures
pytest-language-server fixtures list tests/ --skip-unused
# Show only unused fixtures
pytest-language-server fixtures list tests/ --only-unused
The output includes:
Example output:
Fixtures tree for: /path/to/tests
conftest.py (7 fixtures)
├── another_fixture (used 2 times)
├── cli_runner (used 7 times)
├── database (used 6 times)
├── generator_fixture (used 1 time)
├── iterator_fixture (unused)
├── sample_fixture (used 7 times)
└── shared_resource (used 5 times)
subdir/
└── conftest.py (4 fixtures)
├── cli_runner (used 7 times)
├── database (used 6 times)
├── local_fixture (used 4 times)
└── sample_fixture (used 7 times)
This command is useful for:
Find unused fixtures in your test suite, with CI-friendly exit codes:
# List unused fixtures (text format)
pytest-language-server fixtures unused tests/
# JSON output for programmatic use
pytest-language-server fixtures unused tests/ --format json
Exit codes:
0: All fixtures are used1: Unused fixtures foundExample text output:
Found 4 unused fixture(s):
• iterator_fixture in conftest.py
• auto_cleanup in utils/conftest.py
• temp_dir in utils/conftest.py
• temp_file in utils/conftest.py
Tip: Remove unused fixtures or add tests that use them.
Example JSON output:
[
{"file": "conftest.py", "fixture": "iterator_fixture"},
{"file": "utils/conftest.py", "fixture": "auto_cleanup"},
{"file": "utils/conftest.py", "fixture": "temp_dir"},
{"file": "utils/conftest.py", "fixture": "temp_file"}
]
This command is ideal for:
@pytest.fixture
def my_fixture():
"""Fixture docstring."""
return 42
mocker = pytest.fixture()(_mocker)
@pytest.fixture
async def async_fixture():
return await some_async_operation()
@pytest.fixture
def fixture_a():
return "a"
@pytest.fixture
def fixture_b(fixture_a): # Go to definition works on fixture_a
return fixture_a + "b"
@pytest.mark.usefixtures("database", "cache")
class TestWithFixtures:
def test_something(self):
pass # database and cache are available
@pytest.fixture
def user(request):
return User(name=request.param)
# All parameters treated as fixtures
@pytest.mark.parametrize("user", ["alice", "bob"], indirect=True)
def test_user(user):
pass
# Selective indirect fixtures
@pytest.mark.parametrize("user,value", [("alice", 1)], indirect=["user"])
def test_user_value(user, value):
pass
pytest-language-server correctly implements pytest's fixture shadowing rules:
The LSP correctly handles complex fixture overriding scenarios:
# conftest.py (parent)
@pytest.fixture
def cli_runner():
return "parent runner"
# tests/conftest.py (child)
@pytest.fixture
def cli_runner(cli_runner): # Overrides parent
return cli_runner # Uses parent
# tests/test_example.py
def test_example(cli_runner): # Uses child
pass
When using find-references:
def cli_runner(...) shows references to the child fixturecli_runner(cli_runner) shows references to the parent fixtureAutomatically discovers fixtures from 50+ popular pytest plugins, including:
The server automatically scans your virtual environment for any pytest plugin and makes their fixtures available.
cargo build --release
cargo test
RUST_LOG=debug cargo run
Security is a priority. This project includes:
See SECURITY.md for our security policy and how to report vulnerabilities.
Contributions are welcome! Please feel free to submit a Pull Request.
Install pre-commit hooks:
pre-commit install
Run security checks locally:
cargo audit
cargo clippy
cargo test
MIT License - see LICENSE file for details.
Built with:
Special thanks to the pytest team for creating such an amazing testing framework.
Made with ❤️ and Rust. Blazingly fast 🔥
Built with AI assistance, maintained with care.