4👍
I am the author of said book. I meant that test as more of an introduction to the Django ORM, rather than as a demonstration of best practice, and I try to explain that at the time, but I suppose some confusion was inevitable. I’ll have a think about how I could present things differently.
In any case, if you skip along to a few chapters later in the book, I show how to simplify the test to something that’s more best-practicey.
Whether or not you test basic Django models is up to you — some people will say testing a declarative syntax is over the top, others will say a short test is good to have as a placeholder. Here’s one you might use:
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author)
ISBN = models.CharField(max_length=35)
abstract = models.TextField()
class BookTest(TestCase):
def test_defaults(self):
book = Book()
self.assertEqual(book.title, '')
self.assertEqual(book.author, None)
self.assertEqual(book.ISBN, '')
self.assertEqual(book.abstract, '')
So that’s a placeholder. It encourages you to add more tests if you start introducing more complex fields like, say, a publication_date
field which has a default value of datetime.today() + one_month
, which might warrant a bit of testing to make sure you get it right. Having a placeholder lowers the barrier to subsequent tests. Other people will tell you that’s over the top. You have to find your own balance.
One thing that’s pretty widely accepted is that you should definitely test behaviour. So, if your model has a custom method:
class Book(models.Model):
# [...]
def is_available(self):
return self.pub_date < datetime.today() and Stock.objects.filter(book=self).count() > 0
Then some sort of test for that is definitely a good idea.
1👍
This is where model factories would help a lot. There are two popular modules that provide it:
I’ve personally used factory_boy
and find it very easy to use.
Basically, you define a factory with default field values:
class UserFactory(factory.Factory):
class Meta:
model = models.User
first_name = 'John'
last_name = 'Doe'
admin = False
Then, you can use the factory and override field values if needed. It also supports Sequences, Lazy Attributes and other useful features for generating the data.
Speaking about your particular task, try not to test what django actually has tests for. For example, there is no need to test whether required
argument works. Test your custom model logic involved in manipulating the model.
Also, A Guide to Testing in Django
is a good read.
Hope that helps.
- [Django]-OAuth2 specification states that 'perms' should now be called 'scope'. Please update. Django Facebook connect
- [Django]-'str' object has no attribute '_meta' error when setting up django-comments-xtd per documentation
- [Django]-Django 1.8 does not work on CentOs 6.5 server
1👍
Why would you test the saving and loading of values to the database? That’s Django’s responsibility. Django has a whole suite of tests that check in detail that its database layer is working. There is absolutely no reason to check the basic behaviour of any of your fields, let alone all of them.
Your unit tests are for your logic: your custom methods, your views, your template tags. They are not for logic that is provided by Django by default.
- [Django]-Django: reverse parametrized url in JavaScript
- [Django]-Django: Direct assignment to the forward side of a many-to-many set is prohibited. Use user.set() instead