Documentation Index
Fetch the complete documentation index at: https://mintlify.com/pymupdf/pymupdf4llm-mcp/llms.txt
Use this file to discover all available pages before exploring further.
The project uses pytest for testing, with inline-snapshot for golden-file style assertions and pytest-cov for coverage reporting. Tests are deterministic and run against a bundled minimal PDF fixture so no external files are required.
Running Tests
Run the full test suite with a single Make target:
make test
# equivalent to:
uv run python -m pytest --inline-snapshot=report --cov --cov-config=pyproject.toml --cov-report=xml
This collects all tests under tests/, checks inline snapshots for drift, measures branch coverage, and writes a coverage.xml report.
To iterate quickly on a single file during development, run pytest directly against it:uv run pytest tests/test_tool.py -v
Test Structure
Tests live in the tests/ directory alongside a small PDF fixture:
| Path | Purpose |
|---|
tests/test_tool.py | Tests for the convert_pdf_to_markdown function |
tests/dummy.pdf | Minimal single-page PDF used as a test fixture |
The test file exercises both code paths exposed by convert_pdf_to_markdown — inline conversion and file-save conversion — and pins their output with snapshot assertions:
import tempfile
from pathlib import Path
from inline_snapshot import snapshot
from pymupdf4llm_mcp.app import convert_pdf_to_markdown
_HERE = Path(__file__).parent
dummy_pdf_path = _HERE / "dummy.pdf"
def test_convert_pdf_to_markdown():
result = convert_pdf_to_markdown(dummy_pdf_path.as_posix())
assert result["success"] is True
assert "markdown_content" in result
assert result["markdown_content"] == snapshot("""\
# **Dummy PDF file**
-----
""")
# temporary file to write the markdown content
with tempfile.NamedTemporaryFile(suffix=".md", delete=False) as temp_file:
temp_file_path = Path(temp_file.name)
result = convert_pdf_to_markdown(dummy_pdf_path.as_posix(), save_path=temp_file_path.as_posix())
assert result["success"] is True
assert "markdown_path" in result
assert result["markdown_path"] == temp_file_path.expanduser().resolve().absolute().as_posix()
with open(temp_file_path, encoding="utf-8") as f:
content = f.read()
assert content == snapshot("""\
# **Dummy PDF file**
-----
""")
The test covers two scenarios:
- Inline conversion — calls
convert_pdf_to_markdown without a save_path and asserts the result contains a markdown_content key with the expected Markdown string
- File-save conversion — calls
convert_pdf_to_markdown with a save_path pointing to a temporary file, asserts the result contains a markdown_path key with the resolved absolute path, then reads the file and checks its contents against a snapshot
Both paths share the same snapshot value because the same PDF produces the same Markdown regardless of how the output is delivered.
Snapshot Testing
Snapshots are stored inline in the test source using the inline-snapshot library. When a test runs with --inline-snapshot=report (the default via make test), any drift between actual output and the stored snapshot causes the test to fail without modifying the file.
To update snapshots after an intentional change to the Markdown output:
make snapshot
# equivalent to:
uv run python -m pytest --inline-snapshot=fix --cov --cov-config=pyproject.toml --cov-report=xml
The --inline-snapshot=fix flag rewrites the snapshot strings in-place to match the current output.
Always review snapshot updates carefully before committing. An unintended change to the Markdown output will pass make snapshot silently, replacing the correct expected value with a broken one. Diff the file after running make snapshot to confirm only expected lines changed.
Coverage
Coverage is configured in pyproject.toml under [tool.coverage]:
[tool.coverage.report]
skip_empty = true
[tool.coverage.run]
branch = true
source = ["pymupdf4llm_mcp"]
omit = ["tests/*", "pymupdf4llm_mcp/cli.py"]
Key points:
- Source: only the
pymupdf4llm_mcp package is measured — test files themselves are excluded
- Branch coverage: enabled, so both sides of every conditional are tracked
cli.py excluded: the CLI entry point is thin glue code that wires up Typer and is not exercised by the unit tests
- Output: coverage is written to
coverage.xml in the project root, which CI picks up for reporting
Cross-Version Testing with tox
The project officially supports Python 3.10, 3.11, 3.12, and 3.13. To verify compatibility across all supported interpreters, run tox:
tox creates an isolated environment for each Python version and runs the full pytest suite inside each one. This requires all target versions to be installed locally. If they are not, you can skip this step — CI runs tox automatically on every pull request and will catch cross-version regressions for you.