"""Unit tests for demographics logic layer.""" import json from unittest import mock from unittest.mock import MagicMock import pytest from analytics.connectors import redis from analytics.consts import analytics as consts from analytics.models import demographics as demographics_models, utils @pytest.fixture() def mock_snowflake(monkeypatch, mock_config): """Mock for Snowflake database client.""" snowflake_mock = MagicMock() monkeypatch.setattr( 'analytics.models.demographics.snowflake_conn', snowflake_mock) snowflake_mock.fetchall.return_value = [] return snowflake_mock def test_get_cohorts_no_store_id_filter_when_requesting_all_possible_stores( monkeypatch, mock_snowflake): """Test no filter by store id applied when all stores requested.""" get_sql_mock = mock.Mock() monkeypatch.setattr(demographics_models, '_get_summary_demographics_sql', get_sql_mock) monkeypatch.setattr(redis.client, 'get', MagicMock(return_value=None)) monkeypatch.setattr(redis.client, 'set', MagicMock()) demographics_models.get_cohorts( store_ids=consts.AVAILABLE_DEMOGRAPHICS_STORE_IDS, start_date='2017-05-01', end_date='2017-05-02', labelid=1, subaccountid=2, isrcs=['3'], artist_ids=[1, 2, 3], territory_code='US', region_code='101' ) get_sql_mock.assert_called_once_with({ 'query': 'get_summary_demographics', 'start_date': '2017-05-01', 'end_date': '2017-05-02', 'store_ids': [None], 'labelid': 1, 'subaccountid': 2, 'isrcs': ['3'], 'artist_ids': [1, 2, 3], 'territory_code': 'US', 'region_code': '101'}) redis.client.get.assert_called redis.client.set.assert_called def test_audience_page_apple_music(monkeypatch, mock_snowflake): """Test no filter by store id applied when all stores requested.""" get_sql_mock = mock.Mock() monkeypatch.setattr(demographics_models, '_get_summary_demographics_sql', get_sql_mock) monkeypatch.setattr(redis.client, 'get', MagicMock(return_value=None)) monkeypatch.setattr(redis.client, 'set', MagicMock()) demographics_models.get_cohorts( store_ids=consts.AVAILABLE_DEMOGRAPHICS_STORE_IDS, start_date='2017-05-01', end_date='2017-05-02', labelid=1, subaccountid=2, isrcs=['3'], artist_ids=[1, 2, 3], territory_code='US', region_code='101' ) get_sql_mock.assert_called_once_with({ 'query': 'get_summary_demographics', 'start_date': '2017-05-01', 'end_date': '2017-05-02', 'store_ids': [None], 'labelid': 1, 'subaccountid': 2, 'isrcs': ['3'], 'artist_ids': [1, 2, 3], 'territory_code': 'US', 'region_code': '101'}) redis.client.get.assert_called redis.client.set.assert_called def test_get_cohorts_raises_value_error(monkeypatch, mock_snowflake): """Test get cohorts raises ValueError in case of invalid store_ids.""" monkeypatch.setattr(redis.client, 'get', MagicMock(return_value=None)) monkeypatch.setattr(redis.client, 'set', MagicMock()) with pytest.raises(ValueError): demographics_models.get_cohorts( store_ids={3, 14, 15, 92, 6}, start_date='2017-05-01', end_date='2017-05-02', labelid=1, subaccountid=2, isrcs=['3'], artist_ids=[1, 2, 3], territory_code='US', region_code='101' ) redis.client.get.assert_called redis.client.set.assert_not_called def test_get_cohorts_empty(monkeypatch, mock_snowflake): """Test empty response is returned when no data is found.""" monkeypatch.setattr(redis.client, 'get', MagicMock(return_value=None)) monkeypatch.setattr(redis.client, 'set', MagicMock()) response = demographics_models.get_cohorts( store_ids=consts.AVAILABLE_DEMOGRAPHICS_STORE_IDS, start_date='2017-05-01', end_date='2017-05-02', labelid=1, subaccountid=2, isrcs=['3'], artist_ids=[1, 2, 3], territory_code='US', region_code='101') assert response.message is None assert response.errors is None assert response.status == 204 redis.client.get.assert_called redis.client.set.assert_not_called def test_get_cohorts_sorted( monkeypatch, mock_snowflake, demographics_db_result): """Test empty response is returned when no data is found.""" get_sql_mock = mock.Mock() monkeypatch.setattr(demographics_models, '_get_summary_demographics_sql', get_sql_mock) mock_snowflake.fetchall.return_value = demographics_db_result monkeypatch.setattr(redis.client, 'get', MagicMock(return_value=None)) monkeypatch.setattr(redis.client, 'set', MagicMock()) response = demographics_models.get_cohorts( store_ids=consts.AVAILABLE_DEMOGRAPHICS_STORE_IDS, start_date='2017-05-01', end_date='2017-05-02', labelid=1, subaccountid=2, isrcs=['3'], artist_ids=[1, 2, 3], territory_code='US', region_code='101' ) cohorts = [demographics_models.Cohort(*c) for c in demographics_db_result] expected_result = [cohorts[2], cohorts[1], cohorts[0]] assert response.message == expected_result redis.client.get.assert_called redis.client.set.assert_called def test_redis_cache_miss_stores_result( monkeypatch, mock_snowflake, demographics_db_result): """Test proper result is cached when not found in cache.""" get_sql_mock = mock.Mock() monkeypatch.setattr(demographics_models, '_get_summary_demographics_sql', get_sql_mock) mock_snowflake.fetchall.return_value = demographics_db_result monkeypatch.setattr(redis.client, 'get', MagicMock(return_value=None)) monkeypatch.setattr(redis.client, 'set', MagicMock()) response = demographics_models.get_cohorts( store_ids=consts.AVAILABLE_DEMOGRAPHICS_STORE_IDS, start_date='2017-05-01', end_date='2017-05-02', labelid=1, subaccountid=2, isrcs=['3'], artist_ids=[1, 2, 3], territory_code='US', region_code='101' ) cohorts = [demographics_models.Cohort(*c) for c in demographics_db_result] expected_result = [cohorts[2], cohorts[1], cohorts[0]] assert response.message == expected_result redis.client.get.assert_called_with( ('get_summary_demographics:1:2:2017-05-01:' '2017-05-02:3:1,286:1,2,3:US:101')) redis.client.set.assert_called_with( ('get_summary_demographics:1:2:2017-05-01:' '2017-05-02:3:1,286:1,2,3:US:101'), json.dumps(expected_result)) def test_redis_cache_hit_returns_result( monkeypatch, demographics_db_result): """Test proper result is returned when found in cache.""" cohorts = [demographics_models.Cohort(*c) for c in demographics_db_result] expected_result = [cohorts[2], cohorts[1], cohorts[0]] monkeypatch.setattr( redis.client, 'get', MagicMock( return_value=json.dumps(expected_result).encode())) monkeypatch.setattr(redis.client, 'set', MagicMock()) response = demographics_models.get_cohorts( store_ids=consts.AVAILABLE_DEMOGRAPHICS_STORE_IDS, start_date='2017-05-01', end_date='2017-05-02', labelid=1, subaccountid=2, isrcs=['3'], artist_ids=[1, 2, 3], territory_code='US', region_code='101' ) redis.client.get.assert_called_with( ('get_summary_demographics:1:2:2017-05-01:' '2017-05-02:3:1,286:1,2,3:US:101')) redis.client.set.assert_not_called assert response.message == expected_result def test_get_key(monkeypatch): """Test that key construction returns properly sorted and formatted key.""" monkeypatch.setattr(redis.client, 'set', MagicMock()) key = utils.get_cache_key({ 'query': 'get_summary_demographics', 'labelid': 7163, 'subaccountid': 900, 'start_date': '2017-10-01', 'end_date': '2017-10-31', 'isrcs': ['BRUXD1300156', 'BRRGE1508701'], 'store_ids': [286, 4], 'artist_ids': [585, 45], 'territory_code': 'US', 'region_code': '101'}) assert key == ('get_summary_demographics:7163:900:2017-10-01:2017-10-31:' 'BRRGE1508701,BRUXD1300156:4,286:45,585:US:101') def test_get_key_no_artist_ids(monkeypatch): """Test that key construction returns properly sorted and formatted key.""" monkeypatch.setattr(redis.client, 'set', MagicMock()) key = utils.get_cache_key({ 'query': 'get_summary_demographics', 'labelid': 7163, 'subaccountid': 900, 'start_date': '2017-10-01', 'end_date': '2017-10-31', 'isrcs': ['BRUXD1300156', 'BRRGE1508701'], 'store_ids': [286, 4], 'artist_ids': None, 'territory_code': 'US', 'region_code': '101'}) assert key == ('get_summary_demographics:7163:900:2017-10-01:2017-10-31:' 'BRRGE1508701,BRUXD1300156:4,286:None:US:101') def test_get_key_no_isrcs(monkeypatch): """Test that key construction returns properly sorted and formatted key.""" monkeypatch.setattr(redis.client, 'set', MagicMock()) key = utils.get_cache_key({ 'query': 'get_summary_demographics', 'labelid': 7163, 'subaccountid': 900, 'start_date': '2017-10-01', 'end_date': '2017-10-31', 'isrcs': [None], 'store_ids': [286, 4], 'artist_ids': [585, 45], 'territory_code': 'US', 'region_code': '101'}) assert key == ('get_summary_demographics:7163:900:2017-10-01:2017-10-31:' 'None:4,286:45,585:US:101') def test_get_key_no_subaccount(monkeypatch): """Test that key construction returns properly sorted and formatted key.""" monkeypatch.setattr(redis.client, 'set', MagicMock()) key = utils.get_cache_key({ 'query': 'get_summary_demographics', 'labelid': 7163, 'subaccountid': None, 'start_date': '2017-10-01', 'end_date': '2017-10-31', 'isrcs': ['BRUXD1300156', 'BRRGE1508701'], 'store_ids': [286, 4], 'artist_ids': [585, 45], 'territory_code': 'US', 'region_code': '101'}) assert key == ('get_summary_demographics:7163:None:2017-10-01:2017-10-31:' 'BRRGE1508701,''BRUXD1300156:4,286:45,585:US:101') def test_get_key_no_territory_code(monkeypatch): """Test that key construction returns properly sorted and formatted key.""" monkeypatch.setattr(redis.client, 'set', MagicMock()) key = utils.get_cache_key({ 'query': 'get_summary_demographics', 'labelid': 7163, 'subaccountid': None, 'start_date': '2017-10-01', 'end_date': '2017-10-31', 'isrcs': ['BRUXD1300156', 'BRRGE1508701'], 'store_ids': [286, 4], 'artist_ids': [585, 45], 'territory_code': None, 'region_code': '101'}) assert key == ('get_summary_demographics:7163:None:2017-10-01:2017-10-31:' 'BRRGE1508701,BRUXD1300156:4,286:45,585:None:101') def test_get_key_no_region_code(monkeypatch): """Test that key construction returns properly sorted and formatted key.""" monkeypatch.setattr(redis.client, 'set', MagicMock()) key = utils.get_cache_key({ 'query': 'get_summary_demographics', 'labelid': 7163, 'subaccountid': None, 'start_date': '2017-10-01', 'end_date': '2017-10-31', 'isrcs': ['BRUXD1300156', 'BRRGE1508701'], 'store_ids': [286, 4], 'artist_ids': [585, 45], 'territory_code': None, 'region_code': None}) assert key == ('get_summary_demographics:7163:None:2017-10-01:2017-10-31:' 'BRRGE1508701,''BRUXD1300156:4,286:45,585:None:None')