Skip to content

Coverage error with green's DjangoRunner #227

@MxFlix

Description

@MxFlix

When using coverage with green in django, all import statements, class heads and function heads (presumably etc.) are marked as not covered. I have no idea about the inner workings of the TestRunner, Django, Green and Coverage, but could it maybe be that coverage is "started" to late, and doesn't catch the initial import of these files? (As all those things are lines that are evaluated when the file is first read by Python)

It does work perfectly fine when using django's standard testRunner.

For example, here is the test.py:

from django.test import TestCase

import main.models


class MainTests(TestCase):
    def test_setting_and_retrieving_setting_works(self):
        """Setting and retrieving a setting work as expected.
        """
        setting_name = "some setting"
        setting_value = "a value"
        main.models.Settings.set_setting(setting_name, setting_value)
        self.assertEqual(
            setting_value, main.models.Settings.get_setting(setting_name)
        )

    def test_trying_to_get_an_unset_setting_returns_none(self):
        """When trying to get an unknown setting, None is returned.
        """
        self.assertIsNone(main.models.Settings.get_setting("Something"))

    def test_trying_to_get_an_unset_setting_returns_default(self):
        """When trying to get an unknown setting, None is returned.
        """
        self.assertEqual(
            "Default", main.models.Settings.get_setting("Something", "Default")
        )

Here is the main/models.py:

from django.db import models
from django.db.utils import OperationalError


class Settings(models.Model):
    """
    Stores settings as simple key/value pairs. These can then be used elsewhere in the app.
    """

    name = models.CharField(max_length=200, primary_key=True)
    value = models.CharField(max_length=200)

    @classmethod
    def get_setting(cls, name: str, default: str = None) -> str:
        """Retrieves a setting's value, or None if it doesn't exist."""
        try:
            return cls.objects.get(pk=name).value
        except (cls.DoesNotExist, OperationalError):
            return default

    @classmethod
    def set_setting(cls, name: str, value: str) -> None:
        """Sets the specified setting to the specified value, creates it if it doesn't exist."""
        cls.objects.update_or_create(name=name, defaults={"value": value})

For completeness sake, here is the .green file:

verbose         = 3
run-coverage    = True
cov-config-file = .coveragerc
processes = 1

And .coveragerc:

[run]
branch = True

[xml]
output = coverage.xml

And coverage's xml output:

<?xml version="1.0" ?>
<coverage version="5.2" timestamp="1594479177454" lines-valid="14" lines-covered="5" line-rate="0.3571" branches-valid="0" branches-covered="0" branch-rate="1" complexity="0">
	<!-- Generated by coverage.py: https://coverage.readthedocs.io -->
	<!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
	<sources>
		<source>/home/flix/PythonProjects/imagetagger</source>
	</sources>
	<packages>
		<package name="main" line-rate="0.3571" branch-rate="1" complexity="0">
			<classes>
				<class name="models.py" filename="main/models.py" complexity="0" line-rate="0.3571" branch-rate="1">
					<methods/>
					<lines>
						<line number="1" hits="0"/>
						<line number="2" hits="0"/>
						<line number="5" hits="0"/>
						<line number="10" hits="0"/>
						<line number="11" hits="0"/>
						<line number="13" hits="0"/>
						<line number="14" hits="0"/>
						<line number="16" hits="1"/>
						<line number="17" hits="1"/>
						<line number="18" hits="1"/>
						<line number="19" hits="1"/>
						<line number="21" hits="0"/>
						<line number="22" hits="0"/>
						<line number="24" hits="1"/>
					</lines>
				</class>
			</classes>
		</package>
	</packages>
</coverage>

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions