"""Unit tests for MaterializedView class and factory function.""" from unittest.mock import patch import pytest from snowflake_views.materialized_view import load_view_from_config from snowflake_views.materialized_view import MaterializedView view_name = 'view' table_name = 'table' create_select = 'SELECT DATA FROM TABLE' grant_params = { 'privs': 'SELECT', 'role': 'role'} cluster_dims = 'dim_one, dim_two' cache_sql_where_predicate = 'cache_sql_where_predicate' state_sql = 'SELECT STATE FROM TABLE' class TestMaterializedView(object): """Tests for MaterializedView.""" create_sql = ( 'CREATE OR REPLACE TABLE %(db)i.%(schema)i.table AS ' 'SELECT DATA FROM TABLE') grant_sql = 'GRANT SELECT ON %(db)i.%(schema)i.table TO ROLE role' cluster_sql = ( 'ALTER TABLE %(db)i.%(schema)i.table ' 'CLUSTER BY (dim_one, dim_two)') cache_sql = ( 'SELECT * FROM %(db)i.%(schema)i.table ' 'WHERE cache_sql_where_predicate') cache_sql_no_predicate = 'SELECT * FROM %(db)i.%(schema)i.table' @pytest.fixture def materialized_view(self): """Materialized view.""" return MaterializedView( table_name, create_select, grant_params, cluster_dims, state_sql, cache_sql_where_predicate) @pytest.fixture def materialized_view_no_cache_predicate(self): """Materialized view with no cache predicate.""" return MaterializedView( table_name, create_select, grant_params, cluster_dims, state_sql) def test_sets_create_sql(self, materialized_view): """Test sets create SQL.""" assert materialized_view.create_sql == self.create_sql def test_sets_grant_sql(self, materialized_view): """Test sets grant SQL.""" assert materialized_view.grant_sql == self.grant_sql def test_sets_cluster_sql(self, materialized_view): """Test sets cluster SQL.""" assert materialized_view.cluster_sql == self.cluster_sql def test_sets_cache_sql(self, materialized_view): """Test sets cache SQL.""" assert materialized_view.cache_sql == self.cache_sql def test_sets_cache_sql_no_predicate( self, materialized_view_no_cache_predicate): """Test sets cache SQL with no predicate.""" cache_sql = materialized_view_no_cache_predicate.cache_sql assert cache_sql == self.cache_sql_no_predicate def test_sets_state_sql(self, materialized_view): """Test sets state SQL.""" assert materialized_view.state_sql == state_sql class TestLoadViewFromConfig(object): """Tests for load_view_from_config.""" @pytest.fixture def view_config(self): """View config.""" return { view_name: { 'table_name': table_name, 'create_select': create_select, 'grant_params': grant_params, 'cluster_dims': cluster_dims, 'state_sql': state_sql, 'cache_sql_where_predicate': cache_sql_where_predicate}} @pytest.fixture def view_config_no_cache_predicate(self): """View config with no cache predicate.""" return { view_name: { 'table_name': table_name, 'create_select': create_select, 'grant_params': grant_params, 'cluster_dims': cluster_dims, 'state_sql': state_sql}} @pytest.fixture def invalid_view_config(self): """Invalid view config.""" return {view_name: {}} @pytest.fixture def mock_view_config(self, view_config): """Mock view config.""" with patch( 'snowflake_views.materialized_view.' 'VIEW_CONFIG', new=view_config) as view_config_mock: yield view_config_mock @pytest.fixture def mock_view_config_no_cache_predicate( self, view_config_no_cache_predicate): """Mock view config with no cache predicate.""" with patch( 'snowflake_views.materialized_view.VIEW_CONFIG', new=view_config_no_cache_predicate) as \ view_config_no_cache_predicate_mock: yield view_config_no_cache_predicate_mock @pytest.fixture def mock_invalid_view_config(self, invalid_view_config): """Mock invalid view config.""" with patch( 'snowflake_views.materialized_view.VIEW_CONFIG', new=invalid_view_config) as invalid_view_config_mock: yield invalid_view_config_mock @pytest.fixture def mock_materialized_view(self): """Mock materialized view.""" with patch('snowflake_views.materialized_view.' 'MaterializedView') as materialized_view_mock: yield materialized_view_mock @pytest.fixture def load_view_from_config(self, mock_view_config): """Load view from config.""" return load_view_from_config(view_name) @pytest.fixture def load_view_from_config_no_predicate( self, mock_view_config_no_cache_predicate): """Load view from config with no cache predicate.""" return load_view_from_config(view_name) @pytest.fixture def load_mock_view_from_config( self, mock_view_config, mock_materialized_view): """Load mock view from config.""" return load_view_from_config(view_name) @pytest.fixture def load_mock_view_from_config_no_predicate( self, mock_view_config_no_cache_predicate, mock_materialized_view): """Load mock view from config with no cache predicate.""" return load_view_from_config(view_name) def test_unknown_view_raises_exception(self): """Test unknown view raises exception.""" with pytest.raises(AssertionError) as e: load_view_from_config('invalid_view_name') assert 'Invalid view name "invalid_view_name"' in str(e) def test_missing_config_key_raises_exception( self, mock_invalid_view_config): """Test missing config key raises exception.""" with pytest.raises(AssertionError) as e: load_view_from_config(view_name) assert 'Cannot find key "table_name" in config' in str(e) def test_returns_view_object(self, load_view_from_config): """Test returns view object.""" assert isinstance(load_view_from_config, MaterializedView) def test_returns_view_object_no_predicate( self, load_view_from_config_no_predicate): """Test returns view object with no cache predicate.""" assert isinstance(load_view_from_config_no_predicate, MaterializedView) def test_view_properly_corrected( self, mock_materialized_view, load_mock_view_from_config): """Test view properly constructed.""" mock_materialized_view.assert_called_with( table_name=table_name, create_select=create_select, grant_params=grant_params, cluster_dims=cluster_dims, state_sql=state_sql, cache_sql_where_predicate=cache_sql_where_predicate) def test_view_properly_corrected_no_predicate( self, mock_materialized_view, load_mock_view_from_config_no_predicate): """Test view properly constructed with no cache predicate.""" mock_materialized_view.assert_called_with( table_name=table_name, create_select=create_select, grant_params=grant_params, cluster_dims=cluster_dims, state_sql=state_sql)