Skip to main content
A roll of duct tape; the instant coverage logo

Instant Coverage

Your new Django site need tests. Nothing super fancy, just enough that you know you’ve not forgotten to close some <div> somewhere and it’s not going to start 500ing next time you deploy. You could write unit tests, but those are boring and your client sure as hell isn’t going to pay for the time.

You’ve got five minutes, though.

Features

Simple

Iterates through a list of URLs and complains if any of them 500.

Magic

Will loudly complain when there are views missing from the list of URLs to test.

Has what you need

Comes with optional mixins for checking links and validating HTML, JSON, your spelling, or WCAG compliance.

Extensible

Easily add tests that will run against every view on your website. If you want tests for things like consistent capitalisation of a particular phrase or the universal inclusion of a particular meta tag, you can have them in minutes.

Portable

Compatible with (and tested against) Django versions 1.5 to 4.2, and Python versions from 2.7 to 3.11.

Changes

Changes made in each release are listed in tags in this repository.

Usage

Install

pip install django-instant-coverage

‘Write’ your tests

You’ll want a tests module somewhere. I keep mine in my PROJECT_DIR, because it’s testing the whole site and not just one app. Wherever you put it, it should be named such that your test runner will find it (tests.py usually works well) and should contain at least the following:

from django.test import TestCase
from instant_coverage import InstantCoverageMixin

class EverythingTest(InstantCoverageMixin, TestCase):
    pass

With that in place, you should be able to run your tests with python manage.py test. They’ll fail, though. You’ll get a list of URLs you’ve not told it to test, looking something like this:

AssertionError: The following views are untested:

('^',) ^$ (index)
('^admin/',) ^$ (index)
('^admin/',) ^logout/$ (logout)
('^admin/',) ^password_change/$ (password_change)
[...]

It’ll probably contain a bunch of URLs you don’t want to test, though, like those from the Django admin app. To quickly exclude entire URL includes, add tuples like the ones shown in the failure you just got to your test’s uncovered_includes attribute:

class EverythingTest(InstantCoverageMixin, TestCase):
    uncovered_includes = [
        ('^admin/',),
    ]

Add paths matching the URLs that you do actually want to test to covered_urls, and add paths that match those you don’t to uncovered_urls. If you forget what’s still missing, run the tests again to get an audit of what’s left.

class EverythingTest(InstantCoverageMixin, TestCase):
    covered_urls = [
        '/',
        '/api/',
        '/0007C3F2760E0541/',
    ]

    uncovered_urls = [
        # requires stuff to be in the session
        '/upload/confirm/',
        '/shortlist-selection/',

        # only accepts POST
        '/shortlist-order/',

        # probably tested pretty thoroughly by the django project
        '/media/woof.jpg',
    ]

If you want to use reverse() rather than hard-code URLs or if you want to test more than one path for a given URL, that is fully supported. Encouraged, even. It doesn’t matter how you build it, as long as covered_urls is a list.

If you have views that you can’t test without data present in the database, make a fixtures file and add it to your test class, or create them programmatically in setUp() or setUpTestData() on the test class.

Use the provided optional test mixins

By default, Instant Coverage will make sure none of your views raise unhandled exceptions and all of them return status codes between 200 and 399. There’s a good chance at least some of the provided optional mixins will be appropriate for your website, so be sure to have a look through them and see what strikes your fancy. Use them like this:

from instant_coverage import InstantCoverageMixin, optional

class EverythingTest(
    optional.Spelling, optional.ExternalLinks, optional.ValidHTML5,
    InstantCoverageMixin, TestCase
):
    # covered_urls, etc...

Write your own tests

InstantCoverageMixin provides an instant_responses method that returns a dictionary of Django test client Response objects keyed by URL. Test methods you write should iterate across that. Have a look at the optional mixins for some examples.

If you make any that you think might be useful to any other websites, even if a minority, a pull request would be very much appreciated.

Test under different circumstances

If you want to test all the URLs you’ve listed under different circumstances (for instance, when a user is logged in or when a different language has been selected), create a subclass of your tests and override setUp(). For instance, you might put the following below your EverythingTest:

from django.contrib.auth import get_user_model

class LoggedInEverythingTest(EverythingTest):
    def setUp(self):
        super(LoggedInEverythingTest, self).setUp()
        user = get_user_model()(
            username='user',
            is_staff=True,
            is_superuser=True,
        )
        user.set_password('pass')
        user.save()
        self.assertTrue(self.client.login(username='user', password='pass'))

Be aware that, by default, the test client will follow redirects. If you do not want this, set the follow_redirects attribute of your tests to False. If you have more specific requirements, you may have to override the get_client_kwargs or attempt_to_get_internal_url methods of your test.

If you have a bunch of test classes that test the same collection of URLs, you may want to consider inheriting from InstantCoverageAPI instead of InstantCoverageMixin; the former will not run any tests that you don’t explicitly add yourself.

Metadata

Release files for django-instant-coverage 1.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-instant-coverage 1.2.1
File Size Uploaded Provenance Actions
django-instant-coverage-1.2.1.tar.gz 11.7 kB Without provenance Details for django-instant-coverage-1.2.1.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for django-instant-coverage 1.2.1
File Interpreter ABI Platform Actions
django_instant_coverage-1.2.1-py3-none-any.whl Python 3 none any Details for django_instant_coverage-1.2.1-py3-none-any.whl
django_instant_coverage-1.2.1-py2-none-any.whl Python 2 none any Details for django_instant_coverage-1.2.1-py2-none-any.whl

Total release size: 37.3 kB

Release files / django-instant-coverage-1.2.1.tar.gz

Download URL django-instant-coverage-1.2.1.tar.gz
Size 11.7 kB
Tags Source
SHA-256 checksum
How to use checksums
a8fbc778c429bed2884b7c15be16b4409e6fc2d5d64fee5f4e5060f4e14cd143
BLAKE2b-256 checksum
How to use checksums
8f99f9451bc014a1961ede222af9a92f4133c1eb814c292c9921193d9f1b3fcd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.1

Release files / django_instant_coverage-1.2.1-py3-none-any.whl

Download URL django_instant_coverage-1.2.1-py3-none-any.whl
Size 12.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bc4aba331e38da68d792215a031a3eb7d4d9c6e3bcb992edab7a536ee330f567
BLAKE2b-256 checksum
How to use checksums
c632b70b374cf6d7b7cc905fc11b0bfd6d68bc34bfd547c37186c5f6ef1b7c23
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.1

Release files / django_instant_coverage-1.2.1-py2-none-any.whl

Download URL django_instant_coverage-1.2.1-py2-none-any.whl
Size 12.8 kB
Tags Python 2
SHA-256 checksum
How to use checksums
908fa6aa3452bd28c3b0b242a2f2bb3e5f07bd478d2600aeb15c3b711b6321cb
BLAKE2b-256 checksum
How to use checksums
955a7b0e74c3fb3c754e88a6a21e7e04918a46c8ae3f401a6dd83e99ea9a6abe
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.2 CPython/3.11.1

Security for django-instant-coverage 1.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page