fix: verify date with TDD

- add tests for the function

Signed-off-by: Ameya Shenoy <shenoy.ameya@gmail.com>
This commit is contained in:
Ameya Shenoy 2021-02-14 16:59:35 +05:30
parent e7b0cdaf0c
commit 04d46d06b0
Signed by: codingcoffee
GPG key ID: F7D58AAC5DACF8D3
3 changed files with 76 additions and 10 deletions

View file

@ -79,6 +79,12 @@ docker-compose exec backend python manage.py makemigrations
docker-compose exec backend python manage.py migrate docker-compose exec backend python manage.py migrate
``` ```
- To run unit tests
```sh
docker-compose exec backend python manage.py test
```
Similarly all django commands can be run this way. Similarly all django commands can be run this way.
## Endpoints ## Endpoints

View file

@ -1,3 +1,40 @@
from django.test import TestCase from django.test import TestCase
from unittest import mock
from app.utils import verify_date
import datetime
# Create your tests here. # Create your tests here.
class StubDate(datetime.datetime):
pass
class TestApp(TestCase):
"""Test app utils.
Publish time: datetime.datetime(2021, 2, 14, 12, 30)
"""
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_today_before_publish_time(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 12, 8, 0, 0))
date, _ = verify_date('2021-02-14', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 11).date())
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_today_after_publish_time(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 12, 13, 0, 0))
date, _ = verify_date('2021-02-14', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 12).date())
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_weekend_returns_friday(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 14, 13, 0, 0))
date, _ = verify_date('2021-02-14', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 12).date())
@mock.patch('app.utils.datetime.datetime', StubDate)
def test_a_future_date(self):
StubDate.now = classmethod(lambda cls: datetime.datetime(2021, 2, 15, 13, 0, 0))
date, _ = verify_date('2021-02-20', '')
self.assertEqual(date.date(), datetime.datetime(2021, 2, 15).date())

View file

@ -8,6 +8,7 @@ import csv
import json import json
import datetime import datetime
import logging import logging
from typing import Tuple
from io import BytesIO, TextIOWrapper from io import BytesIO, TextIOWrapper
from zipfile import ZipFile from zipfile import ZipFile
@ -114,7 +115,10 @@ def populate_bhav_copy_data_into_postgres(data=None, date=None):
del data[0] del data[0]
if date is None: if date is None:
date = datetime.datetime.now().date() date = datetime.datetime.now().date()
# data = stocks_csv_to_json(data)
for stock in data: for stock in data:
# stock['date'] = date
# BhavCopyEquity.objects.get_or_create(**stock)
BhavCopyEquity.objects.get_or_create( BhavCopyEquity.objects.get_or_create(
date=date, date=date,
sc_code=int(stock[0]), sc_code=int(stock[0]),
@ -156,17 +160,36 @@ def stocks_csv_to_json(data):
return stocks return stocks
def verify_date(date, ret_message): def verify_date(date, ret_message) -> Tuple[datetime.datetime, str]:
"""Verify current date.
Check current date and time and return the appropriate date. Also take care
of the following usecases
- if today before publish time return yesterdays data
- if today after publish time return todays data
- if a future date, return current day's data with time travel message
- if a weekend return Friday's data with custom message
"""
# Verify Date # Verify Date
logger.info('Verifying date %s', date) logger.info('Verifying date %s', date)
req_date = datetime.datetime.strptime(date, '%Y-%m-%d') curr_datetime = datetime.datetime.now() - datetime.timedelta(hours=5, minutes=30)
# 18:00 IST == 12:30 UTC req_datetime = datetime.datetime.strptime(date, '%Y-%m-%d')
today = datetime.datetime.now().replace(hour=12, minute=30, second=0, microsecond=0) next_publish_time = curr_datetime.replace(hour=6, minute=0, second=0,
logger.info('Req Date: %s; Today: %s', req_date, today) microsecond=0)
if req_date > today: logger.info('Current IST Datetime: %s; Request Datetime: %s; Next Publish: %s',
curr_datetime, req_datetime, next_publish_time)
# Check for future date
if req_datetime.date() > curr_datetime.date():
ret_message = "Time travel not yet invented! Returning latest available data." ret_message = "Time travel not yet invented! Returning latest available data."
req_date = today req_datetime = curr_datetime
if req_date.date() == today.date() and req_date < today: # Check for weekend
req_date = today - datetime.timedelta(days=1) day_num = req_datetime.weekday()
return req_date, ret_message if day_num in [5, 6]:
ret_message = "Markets are closed on weekends. Returning data for Friday."
req_datetime -= datetime.timedelta(days=day_num-4) # change req to Friday
# Check for day
if req_datetime.date() == curr_datetime.date() and curr_datetime < next_publish_time:
ret_message = "Today's data not yet published, returning yesterday's data."
req_datetime -= datetime.timedelta(days=1)
return req_datetime, ret_message