Skip to content

Commit 885053f

Browse files
rboni-dkclaude
andcommitted
test: extract shared unit-test fixtures to testgen.testing (TG-1124)
Move db_session_mock/patched_settings/mcp_user (+ the perm matrix) into an importable testgen.testing.fixtures module so the core test suite and any plugin test suite register them from one source. Conftest discovery does not span separate test trees, so an importable module is the only clean way to share — the core conftests now import from it. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 32b1d82 commit 885053f

4 files changed

Lines changed: 87 additions & 70 deletions

File tree

testgen/testing/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""Testing support importable by the core test suite and any plugin test suite.
2+
3+
Fixtures live in ``testgen.testing.fixtures``; import the ones you need into a
4+
``conftest.py`` to register them (pytest registers fixtures that are merely imported
5+
into a conftest). An importable module is the only way to share fixtures across separate
6+
test trees — sibling test directories do not share conftest fixtures.
7+
"""

testgen/testing/fixtures.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""Reusable pytest fixtures for unit-testing TestGen.
2+
3+
Importable by the core test suite and any plugin test suite. To use, import the fixtures
4+
you need into a ``conftest.py`` — pytest registers fixtures that are imported into a
5+
conftest, preserving their ``autouse`` flag for that subtree::
6+
7+
from testgen.testing.fixtures import db_session_mock, mcp_user # noqa: F401
8+
"""
9+
10+
from unittest.mock import MagicMock, patch
11+
from uuid import uuid4
12+
13+
import pytest
14+
15+
from testgen.mcp.permissions import set_mcp_token, set_mcp_username
16+
17+
# Fictional role matrix for tests. role_a has full access (but NOT view_pii — several
18+
# tests rely on that to exercise the no-view_pii path), role_c is restricted, and
19+
# role_d holds edit + view_pii so deny/allow pairs can be distinguished against a real
20+
# ProjectPermissions without role_a accidentally granting view_pii.
21+
TEST_PERM_MATRIX = {
22+
"view": ["role_a", "role_b"],
23+
"catalog": ["role_a", "role_b", "role_c"],
24+
"edit": ["role_a", "role_d"],
25+
"administer": ["role_a"],
26+
"view_pii": ["role_d"],
27+
}
28+
29+
30+
def _test_roles_with_permission(permission):
31+
return TEST_PERM_MATRIX.get(permission, [])
32+
33+
34+
@pytest.fixture(autouse=True)
35+
def patched_settings():
36+
with patch("testgen.settings.UI_BASE_URL", "http://tg-base-url"):
37+
yield
38+
39+
40+
@pytest.fixture
41+
def db_session_mock():
42+
with patch("testgen.common.models.Session") as factory_mock:
43+
yield factory_mock().__enter__()
44+
45+
46+
@pytest.fixture(autouse=True)
47+
def mcp_user():
48+
"""Set up an authenticated MCP user for all tool tests.
49+
50+
Default: user has 'role_a' on 'demo' project (full access).
51+
The @mcp_permission decorator passes for any permission.
52+
53+
Tests needing scoped access patch _compute_project_permissions directly.
54+
"""
55+
set_mcp_username("test_user")
56+
set_mcp_token("test_bearer_token")
57+
user = MagicMock()
58+
user.id = uuid4()
59+
60+
membership = MagicMock()
61+
membership.project_code = "demo"
62+
membership.role = "role_a"
63+
64+
with (
65+
patch("testgen.common.auth.authorize_token", return_value=user),
66+
patch("testgen.common.models.get_current_session", return_value=MagicMock()),
67+
patch("testgen.mcp.permissions.ProjectMembership") as mock_membership,
68+
patch("testgen.mcp.permissions.PluginHook") as mock_hook,
69+
):
70+
mock_membership.get_memberships_for_user.return_value = [membership]
71+
mock_hook.instance.return_value.rbac.get_roles_with_permission.side_effect = (
72+
_test_roles_with_permission
73+
)
74+
yield user
75+
set_mcp_username(None)
76+
set_mcp_token(None)

tests/unit/conftest.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,2 @@
1-
from unittest.mock import patch
2-
3-
import pytest
4-
5-
6-
@pytest.fixture(autouse=True)
7-
def patched_settings():
8-
with patch("testgen.settings.UI_BASE_URL", "http://tg-base-url"):
9-
yield
10-
11-
12-
@pytest.fixture
13-
def db_session_mock():
14-
with patch("testgen.common.models.Session") as factory_mock:
15-
yield factory_mock().__enter__()
1+
# Importing the fixtures registers them for this test subtree (autouse flags preserved).
2+
from testgen.testing.fixtures import db_session_mock, patched_settings # noqa: F401

tests/unit/mcp/conftest.py

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,2 @@
1-
from unittest.mock import MagicMock, patch
2-
from uuid import uuid4
3-
4-
import pytest
5-
6-
from testgen.mcp.permissions import set_mcp_token, set_mcp_username
7-
8-
# Fictional role matrix for tests. role_a has full access (but NOT view_pii — several
9-
# tests rely on that to exercise the no-view_pii path), role_c is restricted, and
10-
# role_d holds edit + view_pii so deny/allow pairs can be distinguished against a real
11-
# ProjectPermissions without role_a accidentally granting view_pii.
12-
TEST_PERM_MATRIX = {
13-
"view": ["role_a", "role_b"],
14-
"catalog": ["role_a", "role_b", "role_c"],
15-
"edit": ["role_a", "role_d"],
16-
"administer": ["role_a"],
17-
"view_pii": ["role_d"],
18-
}
19-
20-
21-
def _test_roles_with_permission(permission):
22-
return TEST_PERM_MATRIX.get(permission, [])
23-
24-
25-
@pytest.fixture(autouse=True)
26-
def mcp_user():
27-
"""Set up an authenticated MCP user for all tool tests.
28-
29-
Default: user has 'role_a' on 'demo' project (full access).
30-
The @mcp_permission decorator passes for any permission.
31-
32-
Tests needing scoped access patch _compute_project_permissions directly.
33-
"""
34-
set_mcp_username("test_user")
35-
set_mcp_token("test_bearer_token")
36-
user = MagicMock()
37-
user.id = uuid4()
38-
39-
membership = MagicMock()
40-
membership.project_code = "demo"
41-
membership.role = "role_a"
42-
43-
with (
44-
patch("testgen.common.auth.authorize_token", return_value=user),
45-
patch("testgen.common.models.get_current_session", return_value=MagicMock()),
46-
patch("testgen.mcp.permissions.ProjectMembership") as mock_membership,
47-
patch("testgen.mcp.permissions.PluginHook") as mock_hook,
48-
):
49-
mock_membership.get_memberships_for_user.return_value = [membership]
50-
mock_hook.instance.return_value.rbac.get_roles_with_permission.side_effect = (
51-
_test_roles_with_permission
52-
)
53-
yield user
54-
set_mcp_username(None)
55-
set_mcp_token(None)
1+
# Importing the fixture registers the autouse authenticated-MCP-user setup for these tests.
2+
from testgen.testing.fixtures import mcp_user # noqa: F401

0 commit comments

Comments
 (0)