import random from collections import Counter from datetime import date, timedelta from django.test import TestCase from django.contrib.auth import get_user_model from django.utils import timezone from trackstats.models import ( Domain, Metric, StatisticByDate, StatisticByDateAndObject, Period) from trackstats.trackers import ( CountObjectsByDateTracker, CountObjectsByDateAndObjectTracker) from trackstats.tests.models import Comment def to_date(dt): return timezone.make_naive(dt).date() class TrackersTestCase(TestCase): def setUp(self): self.User = get_user_model() self.users_domain = Domain.objects.register(ref='users') self.user_count = Metric.objects.register( domain=self.users_domain, ref='user_count') self.expected_signups = {} dt = timezone.now() - timedelta(days=7) # TODO: Add timezone testing # dt.replace(hour=2) signups_lifetime = 0 while to_date(dt) != date.today(): signups_on_day = random.randint(1, 5) signups_lifetime += signups_on_day self.expected_signups[to_date(dt)] = { 'lifetime': signups_lifetime, 'day': signups_on_day } for i in range(signups_on_day): self.User.objects.create( username='user{}_{}'.format(to_date(dt), i), date_joined=dt) dt += timedelta(days=1) self.expected_signups[date.today()] = self.expected_signups[ date.today() - timedelta(days=1)] def test_count_lifetime(self): CountObjectsByDateTracker( period=Period.LIFETIME, metric=self.user_count, date_field='date_joined').track(self.User.objects.all()) stats = StatisticByDate.objects.narrow( metrics=[self.user_count], period=Period.LIFETIME) for stat in stats: self.assertEqual( stat.value, self.expected_signups[stat.date]['lifetime']) self.assertEqual( stats.count(), len(self.expected_signups)) def test_count_daily(self): CountObjectsByDateTracker( period=Period.DAY, metric=self.user_count, date_field='date_joined').track(self.User.objects.all()) stats = StatisticByDate.objects.narrow( metrics=[self.user_count], period=Period.DAY) for stat in stats: self.assertEqual( stat.value, self.expected_signups[stat.date]['day']) self.assertEqual( stats.count(), # Today is not in there due to group by. len(self.expected_signups) - 1) class ObjectTrackersTestCase(TestCase): def setUp(self): self.User = get_user_model() domain = Domain.objects.register(ref='comments') self.comment_count = Metric.objects.register( domain=domain, ref='comment_count') users = self.users = [ self.User.objects.create(username='user{}'.format(i)) for i in range(5)] dt = timezone.now() - timedelta(days=7) self.expected_daily = {} self.expected_lifetime = Counter() while to_date(dt) <= date.today(): for user in users: comment_count = random.randint(1, 5) for i in range(comment_count): Comment.objects.create( timestamp=dt, user=user) self.expected_lifetime[ (to_date(dt), user.pk)] = self.expected_lifetime[( to_date(dt) - timedelta(days=1), user.pk)] + comment_count self.expected_daily[(to_date(dt), user.pk)] = comment_count dt += timedelta(days=1) def test_count_lifetime(self): CountObjectsByDateAndObjectTracker( period=Period.LIFETIME, metric=self.comment_count, object_model=self.User, object_field='user', date_field='timestamp').track(Comment.objects.all()) stats = StatisticByDateAndObject.objects.narrow( metrics=[self.comment_count], period=Period.LIFETIME) for stat in stats: self.assertEqual( self.expected_lifetime[ (stat.date, stat.object.pk)], stat.value) self.assertEqual( stats.count(), len(self.expected_lifetime)) def test_count_daily(self): CountObjectsByDateAndObjectTracker( period=Period.DAY, metric=self.comment_count, object_model=self.User, object_field='user', date_field='timestamp').track(Comment.objects.all()) stats = StatisticByDateAndObject.objects.narrow( metric=self.comment_count, period=Period.DAY) for stat in stats: self.assertEqual( self.expected_daily[(stat.date, stat.object.pk)], stat.value) self.assertEqual( stats.count(), len(self.expected_daily))