2
\$\begingroup\$

I started learning Django and now I want to write some tests for my application. After reading some blog posts and watching youtube tutorials I wrote tests for URLs. Look at below.

urls.py

from .views import HomeView, ArticleDetailView, CreatePostView, UpdatePostView, DeletePostView, StatisticcsView, CreatePostCategoryView, CategoryView, LikeView, CreateCommentView
    
    urlpatterns = [
        path('', HomeView.as_view(), name="home"),
        path('article/<int:pk>', ArticleDetailView.as_view(), name="article_detail"),
        path('add_post/', CreatePostView.as_view(), name="add_post"),
        path('add_category/', CreatePostCategoryView.as_view(), name="add_category"),
        path('article/edit/<int:pk>', UpdatePostView.as_view(), name="update_post"),
        path('article/delete/<int:pk>', DeletePostView.as_view(), name="delete_post"),
        path('category/<str:cats>/', CategoryView, name="category"),
        path('like/<int:pk>', LikeView, name='like_post'),
        path('statistics/', StatisticcsView.as_view(), name="statistics"),
        path('article/<int:pk>/comment/', CreateCommentView.as_view(), name="add_comment"),
    ]

test_urls.py

from django.test import SimpleTestCase
from django.urls import reverse, resolve
from blog.views import HomeView, ArticleDetailView, CreatePostView, CreatePostCategoryView, UpdatePostView, DeletePostView, CategoryView, LikeView, StatisticcsView, CreateCommentView

class TestBlogUrls(SimpleTestCase):
    
    def test_home_url_is_resolved(self):
        url = reverse('home')
        self.assertEquals(resolve(url).func.view_class, HomeView)

    def test_article_detail_url_is_resolved(self):
        url = reverse('article_detail', args=[1])
        self.assertEquals(resolve(url).func.view_class, ArticleDetailView)

    def test_create_post_url_is_resolved(self):
        url = reverse('add_post')
        self.assertEquals(resolve(url).func.view_class, CreatePostView)

    def test_create_post_category_url_is_resolved(self):
        url = reverse('add_category')
        self.assertEquals(resolve(url).func.view_class, CreatePostCategoryView)

    def test_update_post_url_is_resolved(self):
        url = reverse('update_post', args=[1])
        self.assertEquals(resolve(url).func.view_class, UpdatePostView)

    def test_delete_post_url_is_resolved(self):
        url = reverse('delete_post', args=[1])
        self.assertEquals(resolve(url).func.view_class, DeletePostView)

    def test_category_url_is_resolved(self):
        url = reverse('category', args=['python'])
        self.assertEquals(resolve(url).func, CategoryView)
    
    def test_like_post_url_is_resolved(self):
        url = reverse('like_post', args=[1])
        self.assertEquals(resolve(url).func, LikeView)

    def test_statistics_url_is_resolved(self):
        url = reverse('statistics')
        self.assertEquals(resolve(url).func.view_class, StatisticcsView)

    def test_add_comment_url_is_resolved(self):
        url = reverse('add_comment', args=[1])
        self.assertEquals(resolve(url).func.view_class, CreateCommentView)

My question is if this practice is correct or maybe I can write it better. Thanks in advance.

\$\endgroup\$
4
  • \$\begingroup\$ "if this practice is correct" What do you mean? \$\endgroup\$
    – Mast
    Sep 10, 2020 at 18:31
  • \$\begingroup\$ I mean whether the tests written in this way are correct (do they have any defects). I also try to make sure there is no other, better solution. \$\endgroup\$
    – K.Oleksy
    Sep 10, 2020 at 18:45
  • \$\begingroup\$ You tested them, right? So you think they're correct? \$\endgroup\$
    – Mast
    Sep 10, 2020 at 18:49
  • \$\begingroup\$ Yes, I tested them, and all tests passed. But I am not sure if the solution which I presented is the best practice. I want to make sure that such a solution is in line with good practices. If so, that's perfect, otherwise, I'd like to improve my code. \$\endgroup\$
    – K.Oleksy
    Sep 10, 2020 at 18:57

1 Answer 1

2
\$\begingroup\$

The tests are technically correct, but the value they have doesn't match the amount of time you spent on them. It looks like you're using class-based views, and in such case I'd expect LikeView and CategoryView in the routes should be called the same way as other views, ie. with .as_view(). If my assumption is correct, then your tests should at least catch this bug, otherwise they are just giving you a false feeling of safety that things work. So you'd need to write another set of tests to check yet another aspect of the routes resolving. That feels like you'd spent all your time just by writing tests. And if each test would test a particular tiny piece of functionality, you'll have a hard time during refactoring when a lot of tests will start breaking needlessly.

If you want to test that the routes are resolved correctly, it's usually done by using Test Client and checking the response status is HTTP 200 (or whatever you expect there). But how do you know it was resolved to the correct view? Well you don't, but knowing the name of the resolved class is not really that important. I assume you are (indirectly) testing the whole functionality during development in browser as well, so once the things works, the chance that there will be a regression and a route will suddenly start resolving incorrectly is close to zero. If you want to put even more value in the tests, you should also test the models are modified correctly (eg. after calling delete_post, check if the record is really gone from DB). This kind of tests would look reasonable to me.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.