Right, this is kind of the last place i would like to have asked due to the question being very vague, but I'm at a loss.
Basically, I'm trying to learn how to code and I'm currently working with Django to help me get to grips with the back end of stuff. I keep being reminded of the importance of unit testing so I want to include them in my dummy project that I'm working on so I can begin to understand them early on in my programming journey... only... they seem easy enough on the surface, but are clearly more complicated to a beginner than i gave them credit for.
I'm not entirely sure where / if I'm going wrong here, so feel free to poke me and make fun but try point me in the right direction, or to some beginner friendly resources (scoured the internet and there isn't a massive amount of info).
My project is a dummy GUI related to policing (hoping to use it in my portfolio in future)
Here's the model class I want help with testing. There are others but I want to do those by myself once I know more:
class Warrant(models.Model):
"""
"""
name = models.CharField(max_length=50)
WARRANT_TYPE_CHOICES = (
('ARREST', 'Arrest'),
('SEARCH', 'Search'),
)
warrant_type = models.CharField(max_length=10, choices=WARRANT_TYPE_CHOICES, default='ARREST')
start_date = models.DateTimeField(auto_now=True, null=True)
expiry_date = models.DateTimeField(auto_now_add=True, null=True)
renewal_date = models.DateTimeField(auto_now_add=True, null=True)
As you can see, fairly simple model.
Here are the tests that I'm currently aimlessly fiddling around with:
def test_model_creation(self):
object = Warrant.objects.create()
self.assertIsNotNone(object)
def test_warrant_str(self):
warrant = Warrant.objects.create(
name="Warrant Name",
)
self.assertEqual(str(warrant), "Warrant Name")
def test_datetime_model(self):
start_date = Warrant.objects.create(start_date=datetime.now())
expiry_date = Warrant.objects.create(expiry_date=datetime.now())
renewal_date = Warrant.objects.create(renewal_date=datetime.now())
To me, this reads fine, and all tests return OK. However, I'm not sure if this is best practise or actually does what I think it should be doing.
In addition, I'm not sure how to test the warrant_type / WARRANT_TYPE_CHOICES field either.
I know this isn't typically the type of question that should be asked here, but I'm essentially just typing stuff at random that I've picked up from tutorials and have no idea if it is even correct.
Thanks
It's good that you think tests first! It's usually not models that you test, but behavior, or in other words, methods. If you add a method to your model with some actual logic in it, then that's a good time to start a test for it. For example:
class Warrant(models.Model):
name = models.CharField(max_length=50)
WARRANT_TYPE_CHOICES = (
('ARREST', 'Arrest'),
('SEARCH', 'Search'),
)
warrant_type = models.CharField(max_length=10, choices=WARRANT_TYPE_CHOICES, default='ARREST')
start_date = models.DateTimeField(auto_now=True, null=True)
expiry_date = models.DateTimeField(null=True)
renewal_date = models.DateTimeField(null=True)
@property
def is_expired(self):
return self.expiry_date < timezone.now()
With as test cases:
import datetime
from .models import Warrant
from django.test import TestCase
from django.utils import timezone
class WarrantTestCase(TestCase):
def test_is_expired_returns_true_if_expiry_date_before_now(self):
now = timezone.now()
hour_ago = now - datetime.timedelta(hours=1)
warrant = Warrant.objects.create(expiry_date=hour_ago)
self.assertTrue(warrant.is_expired)
def test_is_expired_returns_false_if_expiry_date_after_now(self):
now = timezone.now()
in_an_hour = now + datetime.timedelta(hours=1)
warrant = Warrant.objects.create(expiry_date=in_an_hour)
self.assertFalse(warrant.is_expired)
Note that I did remove the properties auto_now_add=True
from the fields expiry_date
and renewal_date
. That is probably behavior that you don't want. I figured this out by writing this test case, because one of the test cases failed when I didn't remove it. Long live tests!