Compare commits

...

5 Commits

Author SHA1 Message Date
bcc5f767ba little cleanup TODO in PiLog simulate() 2020-10-25 11:19:20 -05:00
a0a1aa10f4 wow, unit tests! pi is covered (except for the irc plugin)
I think I'm going to move the irc stuff into a separate project in the
future so I'm not worried about testing that one yet
2020-10-25 11:16:48 -05:00
d5e5343193 have pi simulate via API return a 201 2020-10-25 11:16:23 -05:00
da815a1fc3 provide DRF action to run a pi simulation 2020-10-24 23:58:45 -05:00
ef08cec0fb fix field reference in the PiLog.hit property 2020-10-24 23:58:02 -05:00
4 changed files with 86 additions and 3 deletions

View File

@ -31,6 +31,7 @@ class PiLogManager(models.Manager):
newest = PiLog.objects.create(simulation_x=x, simulation_y=y,
total_count_inside=inside, total_count=total)
# TODO: remove the x, y return values, now that we track them in the object
return newest, x, y
@ -66,4 +67,4 @@ class PiLog(models.Model):
@property
def hit(self):
"""Return if this log entry is inside the unit circle."""
return math.hypot(self.simulation_x, self.simulation.y) < 1
return math.hypot(self.simulation_x, self.simulation_y) < 1

View File

@ -1,12 +1,22 @@
"""Provide pi simulation results."""
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet
from pi.models import PiLog
from pi.serializers import PiLogSerializer
class PiLogViewSet(viewsets.ReadOnlyModelViewSet):
class PiLogViewSet(ReadOnlyModelViewSet):
"""Provide list and detail actions for pi simulation log entries."""
queryset = PiLog.objects.all()
serializer_class = PiLogSerializer
permission_classes = [IsAuthenticated]
@action(detail=False, methods=['post'])
def simulate(self, request):
"""Run one simulation of the pi estimator."""
simulation, _, _ = PiLog.objects.simulate()
return Response(self.get_serializer(simulation).data, 201)

47
tests/test_pi_models.py Normal file
View File

@ -0,0 +1,47 @@
"""Test the pi models."""
from unittest import mock
from django.test import TestCase
from django.utils.timezone import now
from pi.models import PiLog
class PiLogTest(TestCase):
"""Test pi models."""
def test_hit_calculation(self):
"""Test that x,y combinations are properly considered inside or outside the circle."""
hit_item = PiLog(simulation_x=0.0, simulation_y=0.0, total_count=0, total_count_inside=0)
miss_item = PiLog(simulation_x=1.0, simulation_y=1.0, total_count=0, total_count_inside=0)
self.assertTrue(hit_item.hit)
self.assertFalse(miss_item.hit)
def test_value_calculation(self):
"""Test that a simulation's value of pi can be calculated."""
item = PiLog(simulation_x=0.0, simulation_y=0.0, total_count=1000, total_count_inside=788)
zero_item = PiLog(simulation_x=0.0, simulation_y=0.0, total_count=0, total_count_inside=0)
self.assertEqual(item.value, 3.152)
self.assertEqual(zero_item.value, 0.0)
def test_string_repr(self):
"""Test the string repr of a simulation log entry."""
item = PiLog(simulation_x=0.0, simulation_y=0.0, total_count=1000, total_count_inside=788,
created=now())
self.assertIn("(788/1000) @ ", str(item))
def test_simulation_inside_determination(self):
"""Test that running a simulation passes the proper inside value."""
# get at least one simulation in the DB
original_item, _, _ = PiLog.objects.simulate()
with mock.patch('random.random', return_value=1.0):
miss_item, _, _ = PiLog.objects.simulate()
self.assertEqual(miss_item.total_count_inside, original_item.total_count_inside)
with mock.patch('random.random', return_value=0.0):
hit_item, _, _ = PiLog.objects.simulate()
self.assertGreater(hit_item.total_count_inside, original_item.total_count_inside)

25
tests/test_pi_views.py Normal file
View File

@ -0,0 +1,25 @@
"""Test the pi package's views."""
from django.contrib.auth.models import User
from rest_framework.status import HTTP_201_CREATED
from rest_framework.test import APITestCase
from pi.models import PiLog
class PiAPITest(APITestCase):
"""Test pi DRF views."""
def setUp(self):
"""Do pre-test stuff."""
self.client = self.client_class()
self.user = User.objects.create(username='test')
self.client.force_authenticate(user=self.user)
def test_simulate_creates_simulation(self):
"""Test that the simulate action creates a log entry."""
self.assertEqual(PiLog.objects.count(), 0)
resp = self.client.post('/pi/api/simulations/simulate/')
self.assertEqual(resp.status_code, HTTP_201_CREATED)
self.assertEqual(PiLog.objects.count(), 2) # 2 because 0 entry and the real entry