Context
Issue #1 (the input-serialization PR) introduced a real tests/ directory
(test_inputs.py, test_update_readonly.py, test_integration_smoke.py), added
[tool.pytest.ini_options] (asyncio_mode = "auto", testpaths = ["tests"]), and pytest-asyncio.
So the original "there is no tests/ dir" gap is partly closed. This issue covers the remaining
reconciliation.
Problem
.claude/hooks.json runs pytest tests/ guarded on edits to openproject-mcp.py / src/tools/
— the path guard predates the modular layout (overlaps with the .claude tooling issue).
- Root-level
test_*.py (test_tools.py, test_news_tools.py, test_news_validation.py,
test_news_integration.py) are manual scripts run as python test_*.py, outside
testpaths=["tests"], so they are not part of the suite. test_tools.py also relies on awaiting
a @mcp.tool object directly, which doesn't work on the 2.x API (the tool is a FunctionTool;
the awaitable is .fn).
Scope
- Adjust
.claude/hooks.json (and confirm config.json testCommand) so the pytest invocation
matches the real tests/ layout.
- Decide per root script: migrate into
tests/ as proper pytest (network-free, mocked) or
clearly document it as a manual live script (and fix the .fn await issue in test_tools.py if
kept).
Out of scope
Acceptance criteria
uv run pytest is green and is the single source of automated tests.
- The
.claude hooks' pytest command actually runs against tests/.
- Root
test_*.py scripts are either pytest-ified under tests/ or documented as manual.
Type: tests/infra. Depends on / overlaps: #1 and the .claude tooling issue. Label: backlog.
Context
Issue #1 (the input-serialization PR) introduced a real
tests/directory(
test_inputs.py,test_update_readonly.py,test_integration_smoke.py), added[tool.pytest.ini_options](asyncio_mode = "auto",testpaths = ["tests"]), andpytest-asyncio.So the original "there is no
tests/dir" gap is partly closed. This issue covers the remainingreconciliation.
Problem
.claude/hooks.jsonrunspytest tests/guarded on edits toopenproject-mcp.py/src/tools/— the path guard predates the modular layout (overlaps with the
.claudetooling issue).test_*.py(test_tools.py,test_news_tools.py,test_news_validation.py,test_news_integration.py) are manual scripts run aspython test_*.py, outsidetestpaths=["tests"], so they are not part of the suite.test_tools.pyalso relies on awaitinga
@mcp.toolobject directly, which doesn't work on the 2.x API (the tool is aFunctionTool;the awaitable is
.fn).Scope
.claude/hooks.json(and confirmconfig.jsontestCommand) so the pytest invocationmatches the real
tests/layout.tests/as proper pytest (network-free, mocked) orclearly document it as a manual live script (and fix the
.fnawait issue intest_tools.pyifkept).
Out of scope
inputtools robust to MCP clients that serialize object args as JSON strings #1.Acceptance criteria
uv run pytestis green and is the single source of automated tests..claudehooks' pytest command actually runs againsttests/.test_*.pyscripts are either pytest-ified undertests/or documented as manual.Type: tests/infra. Depends on / overlaps: #1 and the
.claudetooling issue. Label: backlog.