mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	analytics: Change tests to use a fixed TIME_ZERO.
Previously, analytics tests used timezone.now or custom datetime objects when creating new realms, users, and streams. This commit adds a fixed TIME_ZERO and a process_last_hour helper function in a new AnalyticsTestCase class, and modifies the existing tests to use them.
This commit is contained in:
		@@ -1,5 +1,4 @@
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.utils.dateparse import parse_datetime
 | 
			
		||||
from django.test import TestCase
 | 
			
		||||
 | 
			
		||||
from datetime import datetime, timedelta
 | 
			
		||||
@@ -17,12 +16,21 @@ from zerver.models import Realm, UserProfile, Message, get_user_profile_by_email
 | 
			
		||||
from typing import Any
 | 
			
		||||
from six import text_type
 | 
			
		||||
 | 
			
		||||
def do_update_past_hour(stat):
 | 
			
		||||
    # type: (CountStat) -> Any
 | 
			
		||||
    return process_count_stat(stat, range_start=timezone.now() - timedelta(seconds=3600),
 | 
			
		||||
                              range_end=timezone.now())
 | 
			
		||||
class AnalyticsTestCase(TestCase):
 | 
			
		||||
    MINUTE = timedelta(seconds = 60)
 | 
			
		||||
    HOUR = MINUTE * 60
 | 
			
		||||
    DAY = HOUR * 24
 | 
			
		||||
    TIME_ZERO = datetime(2042, 3, 14).replace(tzinfo=timezone.utc)
 | 
			
		||||
    TIME_LAST_HOUR = TIME_ZERO - HOUR
 | 
			
		||||
 | 
			
		||||
class TestDataCollectors(TestCase):
 | 
			
		||||
    def process_last_hour(self, stat):
 | 
			
		||||
        # type: (CountStat) -> None
 | 
			
		||||
        # The last two arguments below are eventually passed as the first and
 | 
			
		||||
        # last arguments of lib.interval.timeinterval_range, which is an
 | 
			
		||||
        # inclusive range.
 | 
			
		||||
        process_count_stat(stat, self.TIME_ZERO, self.TIME_ZERO)
 | 
			
		||||
 | 
			
		||||
class TestDataCollectors(AnalyticsTestCase):
 | 
			
		||||
    def create_user(self, email, **kwargs):
 | 
			
		||||
        # type: (str, **Any) -> UserProfile
 | 
			
		||||
        defaults = {'realm': self.realm,
 | 
			
		||||
@@ -55,9 +63,9 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
            'recipient': recipient,
 | 
			
		||||
            'subject': 'whatever',
 | 
			
		||||
            'content': 'hello **world**',
 | 
			
		||||
            'pub_date': timezone.now(),
 | 
			
		||||
            'pub_date': self.TIME_ZERO,
 | 
			
		||||
            'sending_client': sending_client,
 | 
			
		||||
            'last_edit_time': timezone.now(),
 | 
			
		||||
            'last_edit_time': self.TIME_ZERO,
 | 
			
		||||
            'edit_history': '[]'
 | 
			
		||||
        }
 | 
			
		||||
        for key, value in defaults.items():
 | 
			
		||||
@@ -78,16 +86,13 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        # almost every test will need a time_interval, realm, and user
 | 
			
		||||
        end = timezone.now() + timedelta(seconds=7200)
 | 
			
		||||
        self.day_interval = TimeInterval('day', end, 'hour')
 | 
			
		||||
        self.hour_interval = TimeInterval('hour', end, 'hour')
 | 
			
		||||
        self.realm = Realm(domain='analytics.test', name='Realm Test',
 | 
			
		||||
                           date_created=parse_datetime('2016-09-27 01:00:50+00:00'))
 | 
			
		||||
                           date_created=self.TIME_ZERO - 2*self.DAY)
 | 
			
		||||
        self.realm.save()
 | 
			
		||||
        # don't pull the realm object back from the database every time we need its id
 | 
			
		||||
        self.realm_id = self.realm.id
 | 
			
		||||
        self.user = self.create_user('email', is_bot=False, is_active=True,
 | 
			
		||||
                                     date_joined=parse_datetime('2016-09-27 04:20:50+00:00'))
 | 
			
		||||
                                     date_joined=self.TIME_ZERO)
 | 
			
		||||
        self.user_id = self.user.id
 | 
			
		||||
 | 
			
		||||
    def test_human_and_bot_count_by_realm(self):
 | 
			
		||||
@@ -101,14 +106,14 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
 | 
			
		||||
        # TODO these dates should probably be explicit, since the default args for the commands are timezone.now() dependent.
 | 
			
		||||
        self.create_user('test_bot1', is_bot=True, is_active=True,
 | 
			
		||||
                         date_joined=timezone.now() - timedelta(hours=1))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
        self.create_user('test_bot2', is_bot=True, is_active=True,
 | 
			
		||||
                         date_joined=timezone.now() - timedelta(hours=1))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
        self.create_user('test_human', is_bot=False, is_active=True,
 | 
			
		||||
                         date_joined=timezone.now() - timedelta(hours=1))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        for stat in stats:
 | 
			
		||||
            do_update_past_hour(stat)
 | 
			
		||||
            self.process_last_hour(stat)
 | 
			
		||||
 | 
			
		||||
        human_row = RealmCount.objects.filter(realm=self.realm, interval='day',
 | 
			
		||||
                                              property='test_active_humans') \
 | 
			
		||||
@@ -126,15 +131,14 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
        stat = CountStat('add_new_user_test', zerver_count_user_by_realm, {}, 'hour', 'hour')
 | 
			
		||||
 | 
			
		||||
        # add new users to realm in last hour
 | 
			
		||||
        self.create_user('email_1', date_joined=parse_datetime('2016-09-27 03:22:50+00:00'))
 | 
			
		||||
        self.create_user('email_2', date_joined=parse_datetime('2016-09-27 03:15:50+00:00'))
 | 
			
		||||
        self.create_user('email_1', date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
        self.create_user('email_2', date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        # add a new user before an hour
 | 
			
		||||
        self.create_user('email_3', date_joined=parse_datetime('2016-09-27 02:10:50+00:00'))
 | 
			
		||||
        self.create_user('email_3', date_joined=self.TIME_ZERO - 2*self.HOUR)
 | 
			
		||||
 | 
			
		||||
        # check if user added before the hour is not included
 | 
			
		||||
        process_count_stat(stat, range_start=parse_datetime('2016-09-27 03:00:50+00:00'),
 | 
			
		||||
                           range_end=parse_datetime('2016-09-27 04:00:50+00:00'))
 | 
			
		||||
        self.process_last_hour(stat)
 | 
			
		||||
        # do_update is writing the stat.property to all zerver tables
 | 
			
		||||
        row = RealmCount.objects.filter(realm=self.realm, property='add_new_user_test',
 | 
			
		||||
                                        interval='hour').values_list('value', flat=True)[0]
 | 
			
		||||
@@ -150,14 +154,14 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
 | 
			
		||||
        # add some stuff to zerver_*
 | 
			
		||||
        self.create_stream(name='stream1', description='test_analytics_stream',
 | 
			
		||||
                           date_created=parse_datetime('2016-09-27 02:10:50+00:00'))
 | 
			
		||||
                           date_created=self.TIME_ZERO)
 | 
			
		||||
        self.create_stream(name='stream2', description='test_analytics_stream',
 | 
			
		||||
                           date_created=parse_datetime('2016-09-27 02:10:50+00:00'))
 | 
			
		||||
                           date_created=self.TIME_ZERO)
 | 
			
		||||
        self.create_stream(name='stream3', description='test_analytics_stream',
 | 
			
		||||
                           date_created=parse_datetime('2016-09-27 02:10:50+00:00'))
 | 
			
		||||
                           date_created=self.TIME_ZERO)
 | 
			
		||||
 | 
			
		||||
        # run do_pull_from_zerver
 | 
			
		||||
        do_update_past_hour(stat)
 | 
			
		||||
        self.process_last_hour(stat)
 | 
			
		||||
 | 
			
		||||
        # check analytics_* values are correct
 | 
			
		||||
        row = RealmCount.objects.filter(realm=self.realm, interval='day',
 | 
			
		||||
@@ -169,17 +173,17 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
        # type: () -> None
 | 
			
		||||
        # add some active and inactive users that are human
 | 
			
		||||
        self.create_user('inactive_human_1', is_bot=False, is_active=False,
 | 
			
		||||
                         date_joined=timezone.now() - timedelta(hours=1))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
        self.create_user('inactive_human_2', is_bot=False, is_active=False,
 | 
			
		||||
                         date_joined=timezone.now() - timedelta(hours=1))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
        self.create_user('active_human', is_bot=False, is_active=True,
 | 
			
		||||
                         date_joined=timezone.now() - timedelta(hours=1))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        # run stat to pull active humans
 | 
			
		||||
        stat = CountStat('active_humans', zerver_count_user_by_realm,
 | 
			
		||||
                         {'is_bot': False, 'is_active': True}, 'hour', 'hour')
 | 
			
		||||
 | 
			
		||||
        do_update_past_hour(stat)
 | 
			
		||||
        self.process_last_hour(stat)
 | 
			
		||||
 | 
			
		||||
        # get row in analytics table
 | 
			
		||||
        row_before = RealmCount.objects.filter(realm=self.realm, interval='day',
 | 
			
		||||
@@ -187,7 +191,7 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
                                       .values_list('value', flat=True)[0]
 | 
			
		||||
 | 
			
		||||
        # run command again
 | 
			
		||||
        do_update_past_hour(stat)
 | 
			
		||||
        self.process_last_hour(stat)
 | 
			
		||||
 | 
			
		||||
        # check if row is same as before
 | 
			
		||||
        row_after = RealmCount.objects.filter(realm=self.realm, interval='day',
 | 
			
		||||
@@ -202,25 +206,24 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
        stat = CountStat('test_messages_sent', zerver_count_message_by_user, {}, 'hour', 'hour')
 | 
			
		||||
 | 
			
		||||
        self.create_user('human1', is_bot=False, is_active=True,
 | 
			
		||||
                         date_joined=parse_datetime('2016-09-27 04:22:50+00:00'))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        human1 = get_user_profile_by_email('human1')
 | 
			
		||||
        human2 = get_user_profile_by_email('email')
 | 
			
		||||
 | 
			
		||||
        self.create_message(human1, Recipient(human2.id),
 | 
			
		||||
                            pub_date=parse_datetime('2016-09-27 04:30:50+00:00'))
 | 
			
		||||
                            pub_date=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        # run command
 | 
			
		||||
        process_count_stat(stat, range_start=parse_datetime('2016-09-27 04:00:50+00:00'),
 | 
			
		||||
                           range_end=parse_datetime('2016-09-27 05:00:50+00:00'))
 | 
			
		||||
        self.process_last_hour(stat)
 | 
			
		||||
        usercount_row = UserCount.objects.filter(realm=self.realm, interval='hour',
 | 
			
		||||
                                                 property='test_messages_sent').values_list(
 | 
			
		||||
            'value', flat=True)[0]
 | 
			
		||||
        assert (usercount_row == 1)
 | 
			
		||||
 | 
			
		||||
        # run command with dates before message creation
 | 
			
		||||
        process_count_stat(stat, range_start=parse_datetime('2016-09-27 01:00:50+00:00'),
 | 
			
		||||
                           range_end=parse_datetime('2016-09-22 02:00:50+00:00'))
 | 
			
		||||
        process_count_stat(stat, range_start=self.TIME_ZERO - 2*self.HOUR,
 | 
			
		||||
                           range_end=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        # check new row has no entries, old ones still there
 | 
			
		||||
        updated_usercount_row = UserCount.objects.filter(
 | 
			
		||||
@@ -228,7 +231,7 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
                                                 .values_list('value', flat=True)[0]
 | 
			
		||||
 | 
			
		||||
        new_row = UserCount.objects.filter(realm=self.realm, interval='hour', property='test_messages_sent',
 | 
			
		||||
            end_time=datetime(2016, 9, 22, 5, 0).replace(tzinfo=timezone.utc)).exists()
 | 
			
		||||
                                           end_time=self.TIME_ZERO - 3*self.HOUR).exists()
 | 
			
		||||
 | 
			
		||||
        self.assertFalse(new_row)
 | 
			
		||||
 | 
			
		||||
@@ -242,24 +245,23 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
 | 
			
		||||
        # write some messages
 | 
			
		||||
        self.create_user('human1', is_bot=False, is_active=True,
 | 
			
		||||
                         date_joined=parse_datetime('2016-09-27 04:22:50+00:00'))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        human1 = get_user_profile_by_email('human1')
 | 
			
		||||
        human2 = get_user_profile_by_email('email')
 | 
			
		||||
 | 
			
		||||
        self.create_message(human1, Recipient(human2.id),
 | 
			
		||||
                            pub_date=parse_datetime('2016-09-27 04:30:50+00:00'),
 | 
			
		||||
                            pub_date=self.TIME_LAST_HOUR,
 | 
			
		||||
                            content="hi")
 | 
			
		||||
        self.create_message(human1, Recipient(human2.id),
 | 
			
		||||
                            pub_date=parse_datetime('2016-09-27 04:30:50+00:00'),
 | 
			
		||||
                            pub_date=self.TIME_LAST_HOUR,
 | 
			
		||||
                            content="hello")
 | 
			
		||||
        self.create_message(human1, Recipient(human2.id),
 | 
			
		||||
                            pub_date=parse_datetime('2016-09-27 04:30:50+00:00'),
 | 
			
		||||
                            pub_date=self.TIME_LAST_HOUR,
 | 
			
		||||
                            content="bye")
 | 
			
		||||
 | 
			
		||||
        # run command
 | 
			
		||||
        process_count_stat(stat, range_start=parse_datetime('2016-09-27 04:00:50+00:00'),
 | 
			
		||||
                           range_end=parse_datetime('2016-09-27 05:00:50+00:00'))
 | 
			
		||||
        self.process_last_hour(stat)
 | 
			
		||||
 | 
			
		||||
        # check no rows for hour interval on usercount granularity
 | 
			
		||||
        usercount_row = UserCount.objects.filter(realm=self.realm, interval='hour').exists()
 | 
			
		||||
@@ -285,18 +287,17 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
        user = get_user_profile_by_email('email')
 | 
			
		||||
 | 
			
		||||
        self.create_stream(name='stream1', description='test_analytics_stream',
 | 
			
		||||
                           date_created=parse_datetime('2016-09-27 03:10:50+00:00'))
 | 
			
		||||
                           date_created=self.TIME_ZERO - 2*self.HOUR)
 | 
			
		||||
 | 
			
		||||
        stream1 = get_stream('stream1', self.realm)
 | 
			
		||||
        recipient = Recipient(type_id=stream1.id, type=2)
 | 
			
		||||
        recipient.save()
 | 
			
		||||
 | 
			
		||||
        self.create_message(user, recipient, pub_date=parse_datetime('2016-09-27 04:30:50+00:00'),
 | 
			
		||||
        self.create_message(user, recipient, pub_date=self.TIME_LAST_HOUR,
 | 
			
		||||
                            content='hi')
 | 
			
		||||
 | 
			
		||||
        # run command
 | 
			
		||||
        process_count_stat(stat, range_start=parse_datetime('2016-09-27 04:00:50+00:00'),
 | 
			
		||||
                           range_end=parse_datetime('2016-09-27 05:00:50+00:00'))
 | 
			
		||||
        self.process_last_hour(stat)
 | 
			
		||||
 | 
			
		||||
        stream_row = StreamCount.objects.filter(realm=self.realm, interval='hour',
 | 
			
		||||
                                                property='test_messages_to_stream').values_list(
 | 
			
		||||
@@ -308,14 +309,14 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
        stat = CountStat('test_active_humans', zerver_count_user_by_realm,
 | 
			
		||||
                         {'is_bot': False, 'is_active': True}, 'hour', 'hour')
 | 
			
		||||
 | 
			
		||||
        self.realm.date_created = parse_datetime('2016-09-30 01:00:50+00:00')
 | 
			
		||||
        self.realm.date_created = self.TIME_ZERO
 | 
			
		||||
        self.realm.save()
 | 
			
		||||
        self.create_user('human1', is_bot=False, is_active=True,
 | 
			
		||||
                         date_joined=parse_datetime('2016-09-30 04:22:50+00:00'))
 | 
			
		||||
                         date_joined=self.TIME_ZERO)
 | 
			
		||||
 | 
			
		||||
        # run count prior to realm creation
 | 
			
		||||
        process_count_stat(stat, range_start=parse_datetime('2016-09-26 04:00:50+00:00'),
 | 
			
		||||
                           range_end=parse_datetime('2016-09-26 05:00:50+00:00'))
 | 
			
		||||
        process_count_stat(stat, range_start=self.TIME_ZERO - 2*self.HOUR,
 | 
			
		||||
                           range_end=self.TIME_LAST_HOUR)
 | 
			
		||||
        realm_count = RealmCount.objects.values('realm__name', 'value', 'property') \
 | 
			
		||||
                                        .filter(realm=self.realm, interval='hour').exists()
 | 
			
		||||
        # assert no rows exist
 | 
			
		||||
@@ -329,17 +330,17 @@ class TestDataCollectors(TestCase):
 | 
			
		||||
                         {'is_bot': False, 'is_active': True}, 'hour', 'hour')
 | 
			
		||||
 | 
			
		||||
        self.create_user('human1', is_bot=False, is_active=True,
 | 
			
		||||
                         date_joined=parse_datetime('2016-09-27 02:22:50+00:00'))
 | 
			
		||||
                         date_joined=self.TIME_LAST_HOUR)
 | 
			
		||||
 | 
			
		||||
        process_count_stat(stat, range_start=parse_datetime('2016-09-27 01:00:50+00:00'),
 | 
			
		||||
                           range_end=parse_datetime('2016-09-27 05:00:50+00:00'))
 | 
			
		||||
        process_count_stat(stat, range_start=self.TIME_ZERO - 2*self.HOUR,
 | 
			
		||||
                           range_end=self.TIME_ZERO)
 | 
			
		||||
        realm_count = RealmCount.objects.values('end_time', 'value') \
 | 
			
		||||
                                        .filter(realm=self.realm, interval='hour')
 | 
			
		||||
        empty1 = realm_count.filter(end_time=datetime(2016, 9, 27, 2, 0, tzinfo=timezone.utc)) \
 | 
			
		||||
        empty1 = realm_count.filter(end_time=self.TIME_ZERO - 2*self.HOUR) \
 | 
			
		||||
                            .values_list('value', flat=True)[0]
 | 
			
		||||
        empty2 = realm_count.filter(end_time=datetime(2016, 9, 27, 4, 0, tzinfo=timezone.utc)) \
 | 
			
		||||
        empty2 = realm_count.filter(end_time=self.TIME_LAST_HOUR) \
 | 
			
		||||
                            .values_list('value', flat=True)[0]
 | 
			
		||||
        nonempty = realm_count.filter(end_time=datetime(2016, 9, 27, 5, 0, tzinfo=timezone.utc)) \
 | 
			
		||||
        nonempty = realm_count.filter(end_time=self.TIME_ZERO) \
 | 
			
		||||
                              .values_list('value', flat=True)[0]
 | 
			
		||||
        assert (empty1 == 0)
 | 
			
		||||
        assert (empty2 == 0)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user