Skip to main content
Glama
conftest.py11 kB
from __future__ import annotations import pytest def pytest_addoption(parser: pytest.Parser) -> None: parser.addoption( "--snowflake", action="store_true", default=False, help="Run tests that require live Snowflake access", ) def pytest_configure(config: pytest.Config) -> None: config.addinivalue_line( "markers", "requires_snowflake: mark test to require live Snowflake (skipped unless --snowflake)", ) config.addinivalue_line( "markers", "integration: mark test as integration test (multi-component workflows)", ) config.addinivalue_line( "markers", "living_reports: mark test as living reports functionality test", ) config.addinivalue_line( "markers", "token_efficiency: mark test as token efficiency validation", ) config.addinivalue_line( "markers", "regression: mark test as regression test for specific bug fix", ) config.addinivalue_line( "markers", "property_based: mark test as property-based test (Hypothesis)", ) config.addinivalue_line( "markers", "sql_validation: mark test as SQL validation test", ) config.addinivalue_line( "markers", "catalog: mark test as catalog/metadata test", ) config.addinivalue_line( "markers", "slow: mark test as slow running (>1s)", ) def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]) -> None: if config.getoption("--snowflake"): return skip_marker = pytest.mark.skip(reason="requires --snowflake to run") for item in items: if "requires_snowflake" in item.keywords: item.add_marker(skip_marker) # ============================================================================= # Shared Fixtures for All Tests # ============================================================================= @pytest.fixture def valid_insight(): """Create a valid Insight object for testing. Reduces duplication across living reports tests. """ import uuid from igloo_mcp.living_reports.models import Insight return Insight(insight_id=str(uuid.uuid4()), importance=8, summary="Test insight summary") @pytest.fixture def valid_section(): """Create a valid Section object for testing. Reduces duplication across living reports tests. """ import uuid from igloo_mcp.living_reports.models import Section return Section(section_id=str(uuid.uuid4()), title="Test Section", order=1) @pytest.fixture def report_service(tmp_path): """Create a ReportService with temporary storage. Provides isolated test environment for living reports tests. """ from igloo_mcp.living_reports.service import ReportService reports_root = tmp_path / "reports" reports_root.mkdir() return ReportService(reports_root=reports_root) @pytest.fixture def sql_permissions_default(): """Default SQL permissions for testing. Provides standard allow/disallow lists for SQL validation tests. """ from igloo_mcp.config import SQLPermissions perms = SQLPermissions() return {"allow_list": perms.get_allow_list(), "disallow_list": perms.get_disallow_list(), "permissions": perms} @pytest.fixture def sql_permissions_permissive(): """Permissive SQL permissions for testing. Allows most operations for testing validation logic. """ from igloo_mcp.config import SQLPermissions perms = SQLPermissions(select=True, insert=True, update=True, delete=True, show=True, describe=True) return {"allow_list": perms.get_allow_list(), "disallow_list": perms.get_disallow_list(), "permissions": perms} # ============================================================================= # Configuration and Profile Fixtures # ============================================================================= @pytest.fixture def mock_config_with_profiles(): """Mock configuration with specified profiles. Reusable across test_config.py, test_user_getting_started.py, test_mcp_profile_integration.py. Usage: with mock_config_with_profiles(["dev", "prod"], default="dev"): # Test code """ from pathlib import Path from unittest.mock import Mock, patch def _mock(profiles: list[str], default: str | None = None): config_data: dict[str, dict[str, dict] | str] = {"connections": {profile: {} for profile in profiles}} if default: config_data["default_connection_name"] = default mock_path = Mock(spec=Path) mock_path.exists.return_value = True mock_path.stat.return_value = Mock(st_mtime=123.0) return patch.multiple( "igloo_mcp.profile_utils", get_snowflake_config_path=Mock(return_value=mock_path), _load_snowflake_config=Mock(return_value=config_data), ) return _mock @pytest.fixture def mock_empty_config(): """Mock empty configuration (no profiles). Reusable across multiple test files. """ from pathlib import Path from unittest.mock import Mock, patch def _mock(): mock_path = Mock(spec=Path) mock_path.exists.return_value = True mock_path.stat.return_value = Mock(st_mtime=123.0) return patch.multiple( "igloo_mcp.profile_utils", get_snowflake_config_path=Mock(return_value=mock_path), _load_snowflake_config=Mock(return_value={"connections": {}}), ) return _mock @pytest.fixture def base_config(): """Provide a minimal Config for tool instantiation. Used in test_tool_schemas.py and other tool tests. """ from igloo_mcp.config import Config, SnowflakeConfig return Config(snowflake=SnowflakeConfig(profile="TEST_PROFILE")) # ============================================================================= # Living Reports Fixtures # ============================================================================= @pytest.fixture def temp_reports_dir(tmp_path): """Create temporary reports directory. Used by multiple living reports tests. """ reports_dir = tmp_path / "reports" reports_dir.mkdir(parents=True, exist_ok=True) return reports_dir @pytest.fixture def report_service_with_report(report_service): """Create ReportService with a pre-created test report. Returns (service, report_id) tuple. """ outline = report_service.create_report(title="Test Report", template="empty") return report_service, outline.report_id @pytest.fixture def report_factory(tmp_path): """Create a ReportFactory for generating complex test data. Provides factory methods for creating reports with sections, insights, and various configurations without boilerplate setup code. Usage: report_id, insights = report_factory.create_with_insights(5) report_id, sections, insights = report_factory.create_large_report() """ from tests.factories.report_factory import create_report_factory return create_report_factory(tmp_path) @pytest.fixture def mock_citation(): """Create a mock citation for test insights. Provides a valid citation structure for tests that need citations but don't execute real queries. Usage: insight = { "summary": "Finding", "importance": 8, "citations": [mock_citation] } """ from tests.helpers.schema_validators import create_mock_citation return create_mock_citation("mock-qid-test-123") @pytest.fixture def mock_insight_with_citation(): """Create a valid insight with mock citation. Pre-configured insight that passes citation validation for tests without real query execution. Usage: await tool.execute( proposed_changes={"insights_to_add": [mock_insight_with_citation]} ) """ from tests.helpers.schema_validators import create_insight_with_citation return create_insight_with_citation("Test insight with citation", importance=8, execution_id="mock-test-qid") @pytest.fixture def skip_citation_constraints(): """Constraints dict for skipping citation validation in tests. Use when testing insights without real query execution. Usage: await tool.execute( proposed_changes={...}, constraints=skip_citation_constraints ) """ return {"skip_citation_validation": True} @pytest.fixture def create_test_insight(): """Factory fixture for creating valid test insights. Returns a function that creates insights with guaranteed valid schema. Usage: insight = create_test_insight("Revenue up 25%", importance=9) insight_with_citation = create_test_insight( "Key finding", importance=8, with_citation=True ) """ from tests.helpers.schema_validators import ( create_insight_with_citation, create_valid_insight, ) def _create(summary: str, importance: int, with_citation: bool = False, **kwargs): if with_citation: return create_insight_with_citation(summary, importance, **kwargs) return create_valid_insight(summary, importance, **kwargs) return _create @pytest.fixture def create_test_section(): """Factory fixture for creating valid test sections. Returns a function that creates sections with guaranteed valid schema. Usage: section = create_test_section("Revenue", order=1) section_with_insights = create_test_section( "Findings", order=2, with_insights=[("Finding 1", 8), ("Finding 2", 7)] ) """ from tests.helpers.schema_validators import ( create_section_with_insights, create_valid_section, ) def _create(title: str, order: int, with_insights=None, **kwargs): if with_insights: return create_section_with_insights(title, order, with_insights, **kwargs) return create_valid_section(title, order, **kwargs) return _create # ============================================================================= # Snowflake Service Mocking Fixtures # ============================================================================= @pytest.fixture def fake_snowflake_service(): """Factory fixture for creating FakeSnowflakeService instances. Usage: service = fake_snowflake_service( plans=[FakeQueryPlan(statement=..., rows=...)] ) """ from tests.helpers.fake_snowflake_connector import ( FakeSessionDefaults, FakeSnowflakeService, ) def _create_service(plans, session_defaults=None): defaults = session_defaults or FakeSessionDefaults() return FakeSnowflakeService(plans=plans, session_defaults=defaults) return _create_service

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Evan-Kim2028/igloo-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server