"""Unit tests for YouTube Statistics Workflow.""" import datetime from unittest import mock from unittest.mock import MagicMock import config from conftest import artist_last_stats, artist_statistics_from_table import youtube_with_pyyoutube as youtube class TestYouTubeTracker: """Test YouTube Tracker related methods.""" def test_get_id_from_link(self, processed_links): """Test get_id_from_link method with reverse parameter also.""" config.YOUTUBE_LINK = 'https://youtube.com/channel/' _id = youtube.get_id_from_link(processed_links['youtube']) assert \ _id == 'UC5kuP-o0jopVpHCD8KSrPpg' def test_create_tables_for_the_first_time( self, mock_delete_from_staging_raw, mock_create_staging_raw_youtube_statistics, mock_create_youtube_statistics, mock_select_artists_links, mock_executor, processed_links, get_artists_links, mock_update_profiles): """Test create_tables method working correctly during the first run.""" mock_select_artists_links.return_value = get_artists_links tracker = youtube.YouTubeTracker() tracker.create_tables() called_methods = \ [mock_select_artists_links.called, mock_create_youtube_statistics.called, mock_delete_from_staging_raw.called, mock_create_staging_raw_youtube_statistics.called] for call in called_methods: assert call assert tracker.__first_time__ assert 'cijikin' in tracker.get_profiles().keys() @mock.patch('youtube_with_pyyoutube.YouTubeStatsSFExecutor.' 'select_artists_stats', artist_statistics_from_table) def test_create_tables_not_for_the_first_time( self, mock_delete_from_staging_raw, mock_create_staging_raw_youtube_statistics, mock_create_youtube_statistics, mock_update_profiles, mock_select_artists_links, mock_executor, processed_links, get_artists_links): """Test create_tables method working correctly for not first run.""" mock_select_artists_links.return_value = get_artists_links mock_create_staging_raw_youtube_statistics.return_value, \ mock_create_youtube_statistics.return_value = \ [['already exists']] * 2 tracker = youtube.YouTubeTracker() tracker.create_tables() called_methods = \ [mock_update_profiles.called, mock_select_artists_links.called, mock_create_youtube_statistics.called, mock_delete_from_staging_raw.called, mock_create_staging_raw_youtube_statistics.called] for call in called_methods: assert call assert not tracker.__first_time__ assert 'cijikin' in tracker.get_profiles() @mock.patch('youtube_with_pyyoutube.YouTubeStatsSFExecutor.' 'select_weekly_change') def test_compare_current_and_last_week_stats_for_weekly_statistics( self, mock_select_weekly_change, mock_executor, processed_links): """Test correctness of comparing method calculations.""" def weekly_side_effect(*args, **kwargs): if -6 in list(kwargs.values()): return {'subscribers': 45, 'likes': 230, 'dislikes': 0, 'views': 4345, 'comments': 66} else: return {'subscribers': 70, 'likes': 109, 'dislikes': 0, 'views': 2435, 'comments': 34} mock_select_weekly_change.side_effect = weekly_side_effect current_subscribers = 57 tracker = youtube.YouTubeTracker() calculations = tracker.compare_current_and_last_week_stats( current_subscribers, 'subscribers', artist_last_stats(), 'cijikin') artist_lasts = artist_last_stats()['cijikin'] current_weekly_change = calculations['daily_change_in_subscribers'] + \ weekly_side_effect('cijikin')['subscribers'] assert calculations == { 'current_subscribers': current_subscribers, 'last_week_subscribers': artist_lasts['last_week_subscribers'], 'daily_change_in_subscribers': current_subscribers - artist_lasts[ 'current_subscribers'], 'current_weekly_change_in_subscribers': calculations['daily_change_in_subscribers'] + weekly_side_effect('cijikin')['subscribers'], 'weekly_change_in_subscribers': weekly_side_effect(first_day_of_period=-6)['subscribers'], 'percentage_change_in_subscribers': current_weekly_change / (current_subscribers - current_weekly_change), 'acceleration_subscribers': (calculations['daily_change_in_subscribers'] + weekly_side_effect('cijikin')['subscribers'] - weekly_side_effect(first_day_of_period=-6)['subscribers']) / weekly_side_effect(first_day_of_period=-6)[ 'subscribers'], 'last_processing_date': datetime.date.today(), 'last_week_processing_date': artist_lasts[ 'last_week_processing_date']} @mock.patch('youtube_with_pyyoutube.YouTubeStatsSFExecutor.' 'select_weekly_change') def test_compare_current_and_last_week_stats_for_week_period_statistics( self, mock_select_weekly_change, mock_executor, processed_links): """Test correctness of comparing method calculations.""" def weekly_side_effect(*args, **kwargs): if -6 in list(kwargs.values()): return {'subscribers': 45, 'likes': 230, 'dislikes': 0, 'views': 4345, 'comments': 66} else: return {'subscribers': 70, 'likes': 109, 'dislikes': 0, 'views': 2435, 'comments': 34} tracker = youtube.YouTubeTracker() current_subscribers = 25 mock_select_weekly_change.side_effect = weekly_side_effect calculations = tracker.compare_current_and_last_week_stats( current_subscribers, 'subscribers', artist_last_stats( last_week_processing_date=datetime.date.today( ) - datetime.timedelta(days=7)), 'cijikin') artist_lasts = artist_last_stats( last_week_processing_date=datetime.date.today( ) - datetime.timedelta(days=7))['cijikin'] # checking the calculation when week period ends current_weekly_change = calculations['daily_change_in_subscribers'] + \ weekly_side_effect('cijikin')['subscribers'] assert mock_select_weekly_change.called assert calculations == { 'current_subscribers': current_subscribers, 'last_week_subscribers': artist_lasts['current_subscribers'], 'daily_change_in_subscribers': current_subscribers - artist_lasts['current_subscribers'], 'current_weekly_change_in_subscribers': calculations['daily_change_in_subscribers'] + weekly_side_effect('cijikin')['subscribers'], 'weekly_change_in_subscribers': weekly_side_effect( first_day_of_period=-6)['subscribers'], 'percentage_change_in_subscribers': current_weekly_change / (current_subscribers - current_weekly_change), 'acceleration_subscribers': (calculations['daily_change_in_subscribers'] + weekly_side_effect('cijikin')['subscribers'] - weekly_side_effect(first_day_of_period=-6)['subscribers']) / weekly_side_effect(first_day_of_period=-6)['subscribers'], 'last_processing_date': datetime.date.today(), 'last_week_processing_date': datetime.date.today() } @mock.patch('youtube_with_pyyoutube.YouTubeTracker.get_profiles', artist_last_stats) def test_get_channel_stats( self, mock_executor, mock_executor_context, mock_get_channel_info, mock_compare_current_and_last_week_stats, mock_get_channel): """Test get_channel_stats method.""" tracker = youtube.YouTubeTracker() for artist in artist_last_stats(): tracker.get_channel_stats(artist) assert mock_get_channel_info.called assert mock_compare_current_and_last_week_stats.called assert mock_compare_current_and_last_week_stats.call_count == 1 assert mock_compare_current_and_last_week_stats.call_args[ 0][0]['subscribers'] == 400 @mock.patch('youtube_with_pyyoutube.YouTubeTracker.get_profiles', artist_last_stats) def test_get_likes_dislikes_stats( self, mock_executor, mock_executor_context, mock_get_channel_info, mock_compare_current_and_last_week_stats, mock_get_channel, mock_get_video_ids): """Test get_likes_dislikes_stats method.""" tracker = youtube.YouTubeTracker() for artist in artist_last_stats(): tracker.get_likes_dislikes_stats(artist) assert mock_get_video_ids.called assert mock_compare_current_and_last_week_stats.called assert mock_compare_current_and_last_week_stats.call_count == 2 assert mock_compare_current_and_last_week_stats.call_args[ 0][0]['likes'] == 0 assert mock_compare_current_and_last_week_stats.call_args[ 0][0]['dislikes'] == 0 @mock.patch('youtube_with_pyyoutube.YouTubeTracker.get_profiles', artist_last_stats) def test_get_views_comments_stats( self, mock_executor, mock_executor_context, mock_get_channel_info, mock_compare_current_and_last_week_stats, mock_get_channel, mock_get_video_ids): """Test get_likes_dislikes_stats method.""" tracker = youtube.YouTubeTracker() for artist in artist_last_stats(): tracker.get_views_comments_stats(artist) assert mock_get_video_ids.called assert mock_compare_current_and_last_week_stats.called assert mock_compare_current_and_last_week_stats.call_count == 2 assert mock_compare_current_and_last_week_stats.call_args[ 0][0]['views'] == 76879 assert mock_compare_current_and_last_week_stats.call_args[ 0][0]['comments'] == 0 @mock.patch('youtube_with_pyyoutube.YouTubeTracker.get_profiles', artist_last_stats) def test_get_and_update_stats( self, mock_get_channel_stats, mock_get_likes_dislikes_stats, mock_get_views_comments_stats, mock_executor, mock_executor_context): """Test get_and_update_stats method.""" tracker = youtube.YouTubeTracker() tracker.get_and_update_stats() assert mock_get_channel_stats.called assert mock_get_likes_dislikes_stats.called assert mock_get_views_comments_stats.called @mock.patch('youtube_with_pyyoutube.Api', MagicMock()) def test_perform_tracking( self, mock_create_tables, mock_get_and_update_stats, mock_executor, mock_executor_context, mock_get_profiles, mock_update_profiles): """Test perform_tracking method.""" mock_get_and_update_stats.return_value = dict(stop=False) tracker = youtube.YouTubeTracker() tracker.perform_tracking() assert mock_create_tables.called assert mock_get_and_update_stats.called assert mock_update_profiles.called