3👍
Actually, Django’s generic class-based views are not called generic for no reason.
You can view the source of the both ListView
and CreateView
.
The ListView
has a GET method handler:
class BaseListView(MultipleObjectMixin, View):
"""A base view for displaying a list of objects."""
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty:
# ...
context = self.get_context_data()
return self.render_to_response(context)
Which returns a valid Django response and can be tested in tests.py
.
If you look at the CreateView
, it inherits from BaseCreateView
(just like ListView
inherits from BaseListView
):
class BaseCreateView(ModelFormMixin, ProcessFormView):
"""
Base view for creating an new object instance.
Using this base class requires subclassing to provide a response mixin.
"""
def get(self, request, *args, **kwargs):
# ...
def post(self, request, *args, **kwargs):
# ...
Which also inherits from ProcessFormView
:
class ProcessFormView(View):
"""Render a form on GET and processes it on POST."""
def get(self, request, *args, **kwargs):
"""Handle GET requests: instantiate a blank version of the form."""
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
"""
Handle POST requests: instantiate a form instance with the passed
POST variables and then check if it's valid.
"""
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
The GET request will result in a valid response. As you see, the POST method handler here returns either self.form_valid(form)
or self.form_invalid(form)
depending on the form status.
You can see the source of these two methods in ViewMixin
:
def form_valid(self, form):
"""If the form is valid, redirect to the supplied URL."""
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form):
"""If the form is invalid, render the invalid form."""
return self.render_to_response(self.get_context_data(form=form))
Both of these methods return a valid testable Django responses.
In conclusion, both of your ListBlogPostView
and CreateBlogPostView
can be directly tested in tests.py
. You just need to have a more detailed look at the implementation of Django’s generic views. The power of open-source!
1👍
Testing view
unlike function most of the time will not have a return value. The way that I go about doing it is to assert the html
response.
So for the ListBlogPostView
it depends on what is in the blogpost_list.html
template.
A general view test should look like this:
class ListBlogPostViewTest(TestCase):
def test_blogpost_list_view(self):
response = self.client.get(reverse('blogpost-list'))
html = response.content.decode('utf8')
self.assertTrue(html.startswith('<html>'))
self.assertIn('<title>BlogPost lists</title>', html)
self.assertTrue(html.endswith('</html>'))
For view
that have context
you can actually check if it is being retrieved and passed correctly to view.
blogPost = BlogPost.object.get(id=1)
self.assertEqual(response.context['blogPost'].name, blogPost.name)
How could I ever use a TDD approach to Django?
As for TDD, you just have to test the html
view first before creating it. It really depend on how detail you like to test and find the balance for it. I prefer to test mainly on the context
being set and important html
element is in the view
.
- [Django]-How can I do such a typical unittest?
- [Django]-Examples of use for PickledObjectField (django-picklefield)?
- [Django]-Django DB table names, plural double s
- [Django]-How to use TimeInput widget in Django forms?
- [Django]-Django – Alternatives To File Browser that Work Well With S3
0👍
You can still surely test lot of parameters –
- status code on get and post request
- variables in context data (such as form)
- assert template used
- creation of object on post request in case of create view
- check for permissions using status codes
The thing is tests on django views are technically integration tests. As long as your tests are granular enough, means you don’t test code for forms or models in views, I don’t see any problem provided you follow Classical TDD.
- [Django]-Elasticsearch:Unknown command: 'search_index'
- [Django]-Django Rest Framework 3.7.7 does not handle Null/None ForeignKey values
- [Django]-Django Cannot Connect to SQL Server 2019
- [Django]-Django-Tastypie: How Do You Access (Http)request object in the Bundle?
- [Django]-AngularJS curly braces aren't resolving, but ng-bind works