Django functions definition in views.py not shown in coverage?

607 views Asked by At

I am using coverage in the following way to test my django app:

 DJANGO_SETTINGS_MODULE=$(SETTINGS) coverage run manage.py test -v 2
 DJANGO_SETTINGS_MODULE=$(SETTINGS) coverage report

In my test suite I tests some views:

class TestJSON(TestCase):

    def setUp(self):
        self.client.login(username='admin', password='passwordz')

    def test_bookmarks_json(self):
        translator = User.objects.create_user('normaluser', '[email protected]',
                                              'secretz')
        search = SearchBookmark(
            search="minutes")
        search.save()
        response = self.client.get('/bookmarks_json/')
        ans = json.loads(response.content)[0]
        self.assertEqual(...)

So I am clearly hitting everything defined in that view for '/bookmarks_json/'. Never the less coverage report says that the signature line is not hit, e.g.:

@login_required
def bookmarks_as_json(request):
    bookmarks = SearchBookmark.objects.all()
    data = serializers.serialize("json", bookmarks)
    return HttpResponse(data, content_type='application/json')

I have seen the solution by Ned Batchelder here Django coverage test for URLs 0%, why? and I am guessing it is some how related. As a result I wrote my own test runner:

import os
import sys
import django
from django.conf import settings
from django.test.utils import get_runner

if __name__ == "__main__":
    os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings.dev'
    django.setup()
    TestRunner = get_runner(settings)
    test_runner = TestRunner(verbosity=2)
    failures = test_runner.run_tests(["myapp.tests"])
    sys.exit(bool(failures))

And

   python testrunner.py   # works, def in view.py is reported !

However, I would like to use the normal command ./manage.py test so I was wondering if there is a way to fix this, with out writing my own test runner.

1

There are 1 answers

2
Alasdair On

The real issue with your test seems to be that you do not log in before testing the view. Since the view uses the login_required decorator, the client is redirected, the view doesn't run, so it will show as missing in the coverage report.

You can log in using self.client.login() before your self.client.get() call.

translator = User.objects.create_user('normaluser', '[email protected]',
                                      'secretz')
search = SearchBookmark(
    search="minutes")
search.save()
self.client.login(username='normaluser', password='secretz')
response = self.client.get('/bookmarks_json/')
ans = json.loads(response.content)[0]