patternpythondjangoMinor
Test Driven Development with Django
Viewed 0 times
djangowithdevelopmenttestdriven
Problem
I'm learning TDD with Django and currently I'm testing my
test_reservation_create.py
```
from django.test import TestCase
from django.urls import reverse
from reservations.models import Reservation
from src.factories import UserFactory, GroupFactory, ProfileFactory, TagFactory
class TestCreateReservation(TestCase):
def setUp(self):
persona = UserFactory(groups=(GroupFactory.create(),))
ProfileFactory(user=persona, )
persona.profile.tags.add(TagFactory())
def test_create_view_denies_anonymous(self):
response = self.client.get(reverse('reservation-create'), follow=True)
self.assertRedirects(response, '/login?next=/r/create/')
def test_loads_template_for_user(self):
self.client.login(username='john', password='defaultpassword')
response = self.client.get(reverse('reservation-create'))
self.assertEquals(response.status_code, 200)
def test_create_blank_for_user(self):
self.client.login(username='john', password='defaultpassword')
data = {
'stops-TOTAL_FORMS': u'2',
'stops-INITIAL_FORMS': u'0',
'stops-MIN_NUM_FORMS': u'0',
'stops-MAX_NUM_FORMS': u'1000',
'stops-0-id': u'',
}
response = self.client.post(reverse('reservation-create'), data=data)
self.assertFormError(response,'form','passenger_name','This field is required.')
self.assertFormError(response,'form','passenger_lastname','This field is required.')
self.assertFormError(response,'form','service_date','This field is required.')
self.assertFormError(response,'form','author_alias','This field is required.')
def test_formset_validation(self):
self.client.login(username='john', password='defaultpassword')
data = {
'stops-TOTAL_FORMS': u'2',
'stops-INITIAL_FORMS':
CreateView class. I feel like I'm not using best practices but am not sure on how to improve my code.test_reservation_create.py
```
from django.test import TestCase
from django.urls import reverse
from reservations.models import Reservation
from src.factories import UserFactory, GroupFactory, ProfileFactory, TagFactory
class TestCreateReservation(TestCase):
def setUp(self):
persona = UserFactory(groups=(GroupFactory.create(),))
ProfileFactory(user=persona, )
persona.profile.tags.add(TagFactory())
def test_create_view_denies_anonymous(self):
response = self.client.get(reverse('reservation-create'), follow=True)
self.assertRedirects(response, '/login?next=/r/create/')
def test_loads_template_for_user(self):
self.client.login(username='john', password='defaultpassword')
response = self.client.get(reverse('reservation-create'))
self.assertEquals(response.status_code, 200)
def test_create_blank_for_user(self):
self.client.login(username='john', password='defaultpassword')
data = {
'stops-TOTAL_FORMS': u'2',
'stops-INITIAL_FORMS': u'0',
'stops-MIN_NUM_FORMS': u'0',
'stops-MAX_NUM_FORMS': u'1000',
'stops-0-id': u'',
}
response = self.client.post(reverse('reservation-create'), data=data)
self.assertFormError(response,'form','passenger_name','This field is required.')
self.assertFormError(response,'form','passenger_lastname','This field is required.')
self.assertFormError(response,'form','service_date','This field is required.')
self.assertFormError(response,'form','author_alias','This field is required.')
def test_formset_validation(self):
self.client.login(username='john', password='defaultpassword')
data = {
'stops-TOTAL_FORMS': u'2',
'stops-INITIAL_FORMS':
Solution
The code has a lot of repetitive blocks, a test flow is mixed up with the data and the logic making it difficult to follow, the number of different assertions makes the tests bigger and more complicated.
I think you should have a much more readable code if you would switch to "data-driven tests" with "parameterized tests" (e.g. there is a built-in support in
Also, instead of checking multiple model fields with multiple asserts, try dumping the model to, for example, a dictionary and compare it with a desired dictionary - basically this way you would check all the fields at once. Of course, in this case, in case of a failure, the output would be less clear, but if you have a good test runner like
Other notes:
I think you should have a much more readable code if you would switch to "data-driven tests" with "parameterized tests" (e.g. there is a built-in support in
pytest) or take a look at the ddt package.Also, instead of checking multiple model fields with multiple asserts, try dumping the model to, for example, a dictionary and compare it with a desired dictionary - basically this way you would check all the fields at once. Of course, in this case, in case of a failure, the output would be less clear, but if you have a good test runner like
nose or pytest, this should not be a problem for the number of fields we are talking about.Other notes:
- the user credentials should probably be moved to a single place - to a config file for your tests. This way, if they change, we would need to change it in a single place instead of looking for them in multiple places in the code.
- think about splitting your test case into multiple test cases - e.g. one for access control, the other for validation tests etc.
Context
StackExchange Code Review Q#154863, answer score: 4
Revisions (0)
No revisions yet.