pythondjangotestingdjango-tests

Does this test makes sense?


I'm currently learning how to write tests for a Django application. The guy in the tutorial video wrote the following test for his application:

def test_product_url(self):
    path = reverse('product_detail')
    self.assertEqual(resolve(path).view_name, 'product_detail')

I don't understand how this test makes sense. It just tests if the django resolve functions works correctly right?


Solution

  • What the test does

    Django offers certain functions to generate a URL from a view name (optionally with parameters): the reverse(…) [Django-doc] function. Furthermore the opposite is done with the resolve(…) [Django-doc] function: it calculates what path will be called, from a given URL and returns a ResolverMatch object that contains the view name, as well as a reference to the function, etc.

    If the two functions are implemented correctly - something we as developers have no control about, since we use Django (well of course one can fix bugs and create tickets for the Django development team, but let us ignore that for now), it looks as if the two functions are "inverses" of each other. There might however be some piculiarities.

    Cases where the test might fail

    First of all, the test here implicitly checks that a view with the given name exists: in case no such view exists anymore, the reverse lookup will fail, and raise an error. The test thus ensures that one for example does not - by accident - renames the view.

    Another thing this checks is that the relation between views and URLs is injective: if there are two views producing the same URL, then the function is not injective.

    If for example there are overlapping paths in the sense that these both match a given URL, then it is possible that the resolve(..) function will point to another URL: if for example the view name generates an URL /some/url, but that one is covered by a path earlier in the list of paths as well, then the resulve will have a different name.

    Note however that even if the relation between views and URLs is not injective, then this still does not mean this will raise an error: it is possible that the given view name is the first path, and thus that problem is not "detected".

    Regardless whether this test was intended to check this, it is not a good idea to check this in an ad-hoc fashion: in case one wants to guarantee that all views have a name, etc. It is better to write a test that exhaustively checks all the paths and view names.