I’m working on a side a project while trying to discipline myself to get accustomed to the TDD approach in Django.
I'm not sure why I’m running into this failed test
(venv) osahenru@osahenru ~/D/q-4> pytest -k test_can_post_questions
============================= test session starts ==============================
platform linux -- Python 3.10.12, pytest-8.1.1, pluggy-1.5.0
django: version: 5.0.4, settings: config.settings (from ini)
rootdir: /home/osahenru/Documents/q-4
configfile: pytest.ini
plugins: django-4.8.0
collected 5 items / 4 deselected / 1 selected
app/tests/test_views.py F [100%]
=================================== FAILURES ===================================
______________________ TestEvent.test_can_post_questions _______________________
self = <test_views.TestEvent testMethod=test_can_post_questions>
def test_can_post_questions(self):
event = Event.objects.create(name='Python Ghana')
data = {
'text': 'how are you?',
}
response = self.client.post(reverse('questions', kwargs={'pk': event.id}), data)
> self.assertIsInstance(response.context['form'], QuestionCreateForm)
E TypeError: 'NoneType' object is not subscriptable
app/tests/test_views.py:52: TypeError
=========================== short test summary info ============================
FAILED app/tests/test_views.py::TestEvent::test_can_post_questions - TypeError: 'NoneType' object is not subscriptable
======================= 1 failed, 4 deselected in 0.53s ========================
(venv) osahenru@osahenru ~/D/q-4 [0|1]>
here is the test causing the error message
def test_can_post_questions(self):
event = Event.objects.create(name='Python Ghana')
data = {
'text': 'how are you?',
}
response = self.client.post(reverse('questions', kwargs={'pk': event.id}), data)
self.assertIsInstance(response.context['form'], QuestionCreateForm)
self.assertEqual(response.status_code, 302)
and here is the view function
def questions(request, pk):
event = Event.objects.get(id=pk)
questions = Question.objects.filter(event=event)
form = QuestionCreateForm()
if request.method == 'POST':
form = QuestionCreateForm(request.POST)
if form.is_valid():
question = form.save(commit=False)
question.event = event
question.save()
return redirect('questions', pk=pk)
context = {
'form': form,
'questions': questions,
'event': event
}
return render(request, 'questions.html', context)
Also as a beginner in the TDD approach, is there a boilerplate for writing unit tests in general and specifically for Django? I’m really struggling with this concept. Thanks
The response being tested here is the redirect after the post, which doesn't have a context. If you want to look at the context of the final response, you need to add follow=True
to your self.client.post(
call - see the docs for more about client args
As far as boilerplates go, the main rule of thumb I use is, if I wrote it, I test it. So you don't need to test a form's ability to submit, as django handles that and it's hopefully well tested already. To use your code as an example, I would test that the question.event item gets added as appropriate as that is your own addition to the default submit form process.