"""Unit tests for tasks of Source of Stream Pre-aggregation Workflow.""" import datetime from unittest.mock import ANY from unittest.mock import MagicMock from unittest.mock import Mock from unittest.mock import call from unittest.mock import patch from garcon.contrib.dynamo_feed_status import \ feed_status_ingestion as feed_status import pytest from analytics_aggregation.flows.spotify_sos import tasks from analytics_aggregation.flows.spotify_sos import utils @pytest.fixture() def date_range(): """Date range structure.""" return {'start_date': '2017-01-01', 'end_date': '2017-01-02'} class _DateWithTodayMock(datetime.date): """Mock datetime.date.today to return constant date.""" @classmethod def today(cls): return cls(2017, 1, 1) @pytest.yield_fixture def mock_executor_context(): """Yield executor context.""" sf_executor_class_path = ( 'analytics_aggregation.flows.spotify_sos.tasks.SpotifySOSExecutor') with patch(sf_executor_class_path) as sf_executor: mock_executor_context = sf_executor.return_value.__enter__.return_value yield mock_executor_context @patch('analytics_aggregation.flows.spotify_sos.tasks.datetime') @patch('analytics_aggregation.util.common') def test_extract_date_all_processed(common, date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock activity_mock = MagicMock() is_spotify_ingested_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_spotify_ingested', is_spotify_ingested_mock) get_overall_feed_status_mock = MagicMock( return_value=feed_status.STATUS_INGESTED) monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) tasks.extract_date(activity_mock, 'feed_name', None, None) assert common.exit_message.called_with( 'There is no data to aggregate for 2016-12-25_2017-01-01 range') @patch('analytics_aggregation.flows.spotify_sos.tasks.datetime') def test_extract_date_not_processed(date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock activity_mock = MagicMock() is_spotify_ingested_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_spotify_ingested', is_spotify_ingested_mock) get_overall_feed_status_mock = MagicMock(return_value='bullsquaw') monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) today = '2017-01-01' week_ago = '2016-12-25' result = tasks.extract_date(activity_mock, 'feed_name', None, None) assert not result['reload'] assert result['date_range']['start_date'] == week_ago assert result['date_range']['end_date'] == today result = tasks.extract_date( activity_mock, 'feed_name', '2017-03-30_2017-03-31', True) assert result['reload'] assert result['date_range']['start_date'] == '2017-03-30' assert result['date_range']['end_date'] == '2017-03-31' @patch('analytics_aggregation.flows.spotify_sos.tasks.datetime') def test_find_range_to_process_all_processed(date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock is_spotify_ingested_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_spotify_ingested', is_spotify_ingested_mock) get_overall_feed_status_mock = MagicMock( return_value=feed_status.STATUS_INGESTED) monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) assert tasks._find_range_to_process('feed_name') == { 'found_days': False, 'week_range': '2016-12-25_2017-01-01' } @patch('analytics_aggregation.flows.spotify_sos.tasks.datetime') def test_find_range_to_process_not_processed(date_mock, monkeypatch): """Test extract_date task.""" date_mock.date = _DateWithTodayMock is_spotify_ingested_mock = MagicMock(return_value=True) monkeypatch.setattr( utils, 'is_spotify_ingested', is_spotify_ingested_mock) get_overall_feed_status_mock = MagicMock(return_value='bullsquaw') monkeypatch.setattr( feed_status, 'get_overall_status', get_overall_feed_status_mock) assert tasks._find_range_to_process('feed_name') == { 'found_days': True, 'week_range': '2016-12-25_2017-01-01', 'start_date': '2016-12-25', 'end_date': '2017-01-01' } def test_check_spotify_ingested(monkeypatch, date_range): """Test check_spotify_ingested task.""" is_spotify_ingested_mock = MagicMock() monkeypatch.setattr( utils, 'is_spotify_ingested', is_spotify_ingested_mock) tasks.check_spotify_ingested(Mock(), date_range, True) is_spotify_ingested_mock.assert_has_calls([ call('2017-01-01'), call().__bool__(), call('2017-01-02'), call().__bool__()]) def test_populate_staging_with_spotify_data(date_range, mock_executor_context): """Test populate_staging_with_spotify_data with storeid of Spotify.""" tasks.populate_staging_with_spotify_data( Mock(), date_range) mock_executor_context.populate_staging_sos.assert_called_with( labelids_clause=ANY, params=ANY) def test_cleanup_staging_sos(date_range, mock_executor_context): """Test cleanup_staging_sos.""" tasks.cleanup_staging_sos(Mock(), date_range) tasks.cleanup_staging_sos(Mock(), date_range) mock_executor_context.cleanup_staging_sos.assert_called_with( labelids_clause=ANY, params=ANY) def test_sanity_check_populate_staging_sos(monkeypatch, mock_executor_context): """Test sanity_check_populate_staging_sos.""" activity_mock = MagicMock() capture_mock = MagicMock() monkeypatch.setattr(utils, 'capture_warning', capture_mock) date_range = {'start_date': '2017-03-03', 'end_date': '2017-03-03'} mock_executor_context.get_row_count_from_staging_sos.side_effect = [ 123, 24214] tasks.sanity_check_populate_staging_sos( activity_mock, date_range, reload=False) capture_mock.assert_has_calls([ call( 'Sanity check for the populate_staging_sos performed, the number ' 'of streams is suspicious, please check manually! abs_difference ' 'for Spotify is 24091.', activity_mock)]) mock_executor_context.get_row_count_from_staging_sos.side_effect = [ 123, 121] tasks.sanity_check_populate_staging_sos( activity_mock, date_range, reload=False) activity_mock.assert_has_calls([ call.logger.info( 'Sanity check for the populate_staging_sos performed, everything ' 'is fine, abs_difference for Spotify is 2.')]) mock_executor_context.get_row_count_from_staging_sos.side_effect = [ 123, 124241] tasks.sanity_check_populate_staging_sos( activity_mock, date_range, reload=False) capture_mock.assert_has_calls([ call( 'Sanity check for the populate_staging_sos performed, the number ' 'of streams is suspicious, please check manually! abs_difference ' 'for Spotify is 124118.', activity_mock)])