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:
Rishi Gupta
2016-10-06 16:29:57 -07:00
committed by Tim Abbott
parent 638d9ee262
commit 6996b21480

View File

@@ -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)