"""Unit tests for index.py — ASSERT_SNOWFLAKE_SYNC sections.""" import datetime as dt from unittest.mock import MagicMock import index import pytest _WINDOW = ( dt.datetime(2025, 1, 1, tzinfo=dt.timezone.utc), dt.datetime(2025, 1, 2, tzinfo=dt.timezone.utc), ) _DEFAULT_SUMMARY = {'shouldBeTrue': True} _DEFAULT_COMPARISON = { 'missing_in_snowflake': [], 'missing_in_neo4j': [], 'field_mismatches': [], } @pytest.fixture def mock_build_window(mocker): """Patch build_window to return a fixed time window.""" return mocker.patch( 'src.assert_snowflake_sync.snowflake_sync.build_window', return_value=_WINDOW, ) @pytest.fixture def mock_run_row_level_check(mocker): """Patch run_row_level_check to return default summary and comparison.""" return mocker.patch( 'src.assert_snowflake_sync.snowflake_sync.run_row_level_check', return_value=(_DEFAULT_SUMMARY, _DEFAULT_COMPARISON), ) @pytest.fixture def mock_snowflake_checks(mocker): """Patch CHECKS with a single default check.""" mocker.patch('src.assert_snowflake_sync.checks.CHECKS', [{'name': 'check_1'}]) @pytest.fixture def mock_create_snowflake_executor(mocker): """Patch create_snowflake_executor to return a MagicMock.""" mocker.patch('index.config.create_snowflake_executor', return_value=MagicMock()) class TestRunSnowflakeSyncChecks: """Tests for run_snowflake_sync_checks.""" @pytest.fixture(autouse=True) def _setup(self, mock_build_window, mock_run_row_level_check, mock_snowflake_checks, mock_create_snowflake_executor): self.mock_build = mock_build_window self.mock_run = mock_run_row_level_check def test_calls_build_window(self, neo4j_driver): """build_window is called once to establish the time window.""" index.run_snowflake_sync_checks(neo4j_driver) self.mock_build.assert_called_once() def test_returns_one_result_per_check(self, mocker, neo4j_driver): """Returns one result dict for each check in CHECKS.""" mocker.patch('src.assert_snowflake_sync.checks.CHECKS', [{'name': 'c1'}, {'name': 'c2'}]) results = index.run_snowflake_sync_checks(neo4j_driver) assert len(results) == 2 def test_result_has_correct_structure(self, mocker, neo4j_driver): """Each result has query_name, query='row_level_compare', and result=[summary].""" summary = {'shouldBeTrue': True, 'neo4j_row_count': 5} mocker.patch('src.assert_snowflake_sync.checks.CHECKS', [{'name': 'my_check'}]) self.mock_run.return_value = (summary, _DEFAULT_COMPARISON) results = index.run_snowflake_sync_checks(neo4j_driver) assert results[0]['query_name'] == 'my_check' assert results[0]['query'] == 'row_level_compare' assert results[0]['result'] == [summary] def test_window_passed_to_run_row_level_check(self, neo4j_driver): """window_start and window_end from build_window are forwarded to run_row_level_check.""" index.run_snowflake_sync_checks(neo4j_driver) args = self.mock_run.call_args[0] assert args[3] == _WINDOW[0] assert args[4] == _WINDOW[1] def test_each_check_passed_to_run_row_level_check(self, mocker, neo4j_driver): """Every check in CHECKS is passed individually to run_row_level_check.""" checks = [{'name': 'c1'}, {'name': 'c2'}] mocker.patch('src.assert_snowflake_sync.checks.CHECKS', checks) index.run_snowflake_sync_checks(neo4j_driver) assert self.mock_run.call_count == 2 passed_checks = [call[0][0] for call in self.mock_run.call_args_list] assert passed_checks == checks def test_failing_check_still_returns_result(self, neo4j_driver): """A check with shouldBeTrue=False is included in results without raising.""" summary = { 'shouldBeTrue': False, 'missing_in_snowflake_count': 1, 'missing_in_neo4j_count': 0, 'field_mismatch_count': 0, } comparison = { 'missing_in_snowflake': [('id-1',)], 'missing_in_neo4j': [], 'field_mismatches': [], } self.mock_run.return_value = (summary, comparison) results = index.run_snowflake_sync_checks(neo4j_driver) assert len(results) == 1 assert results[0]['result'][0]['shouldBeTrue'] is False @pytest.fixture def mock_neo4j_driver(mocker): """Patch index.GraphDatabase.driver and return the mock driver instance.""" mock_driver = MagicMock() mocker.patch('index.GraphDatabase.driver', return_value=mock_driver) return mock_driver @pytest.fixture def mock_run_snowflake_sync_checks(mocker): """Patch index.run_snowflake_sync_checks to return [] by default.""" return mocker.patch('index.run_snowflake_sync_checks', return_value=[]) @pytest.fixture def mock_assert_results(mocker): """Patch index.assert_results.""" return mocker.patch('index.assert_results') @pytest.fixture def mock_call_datadog_with_metric(mocker): """Patch index.call_datadog_with_metric.""" return mocker.patch('index.call_datadog_with_metric') class TestMainAssertSnowflakeSync: """Tests for main() when ASSERT_SNOWFLAKE_SYNC is True.""" @pytest.fixture(autouse=True) def assert_snowflake_sync_enabled(self, mocker): """Enable ASSERT_SNOWFLAKE_SYNC for every test in this class.""" mocker.patch('index.config.ASSERT_SNOWFLAKE_SYNC', True) def test_calls_run_snowflake_sync_checks( self, mock_neo4j_driver, mock_run_snowflake_sync_checks): """main() calls run_snowflake_sync_checks with the Neo4j driver.""" index.main() mock_run_snowflake_sync_checks.assert_called_once_with(mock_neo4j_driver) def test_does_not_call_assert_results( self, mock_neo4j_driver, mock_run_snowflake_sync_checks, mock_assert_results): """main() does not call assert_results when ASSERT_SNOWFLAKE_SYNC is True.""" index.main() mock_assert_results.assert_not_called() def test_does_not_send_datadog_metric( self, mock_neo4j_driver, mock_run_snowflake_sync_checks, mock_call_datadog_with_metric): """main() does not send a Datadog metric when ASSERT_SNOWFLAKE_SYNC is True.""" index.main() mock_call_datadog_with_metric.assert_not_called() def test_returns_results_from_run_snowflake_sync_checks( self, mock_neo4j_driver, mock_run_snowflake_sync_checks): """main() returns whatever run_snowflake_sync_checks returns.""" expected = [{'query_name': 'c', 'query': 'row_level_compare', 'result': [{}]}] mock_run_snowflake_sync_checks.return_value = expected result = index.main() assert result == expected