summaryrefslogtreecommitdiff
path: root/django/test/test_coverage.py
blob: 7c22edacb1e96b7816a0fc8eb8f2e5bcbc3f3896 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import coverage, time

import os, sys

from django.conf import settings
from django.db.models.loading import get_app, get_apps

from django.test.simple import DefaultTestRunner as base_run_tests

from django.utils.module_tools import get_all_modules
from django.utils.translation import ugettext as _

def _get_app_package(app_model_module):
    """
    Returns the app module name from the app model module.
    """
    return '.'.join(app_model_module.__name__.split('.')[:-1])


class BaseCoverageRunner(object):
    """
    Placeholder class for coverage runners. Intended to be easily extended.
    """

    def __init__(self):
        """Placeholder (since it is overrideable)"""
        self.cov = coverage.coverage(cover_pylib=True, auto_data=True)
        self.cov.use_cache(True)
        self.cov.load()
        #self.cov.combine()
        


    def run_tests(self, test_labels, verbosity=1, interactive=True,
                  extra_tests=[]):
        """
        Runs the specified tests while generating code coverage statistics. Upon
        the tests' completion, the results are printed to stdout.
        """
        #self.cov.erase()
        #Allow an on-disk cache of coverage stats.
        #self.cov.use_cache(0)
        #for e in getattr(settings, 'COVERAGE_CODE_EXCLUDES', []):
        #    self.cov.exclude(e)


        self.cov.start()
        brt = base_run_tests()
        results = brt.run_tests(test_labels, verbosity, interactive, extra_tests)
        self.cov.stop()
        #self.cov.erase()

        coverage_modules = []
        if test_labels:
            for label in test_labels:
                label = label.split('.')[0]
                app = get_app(label)
                coverage_modules.append(_get_app_package(app))
        else:
            for app in get_apps():
                coverage_modules.append(_get_app_package(app))

        coverage_modules.extend(getattr(settings, 'COVERAGE_ADDITIONAL_MODULES', []))

        packages, self.modules, self.excludes, self.errors = get_all_modules(
            coverage_modules, getattr(settings, 'COVERAGE_MODULE_EXCLUDES', []),
            getattr(settings, 'COVERAGE_PATH_EXCLUDES', []))



        return results

class ConsoleReportCoverageRunner(BaseCoverageRunner):

    def run_tests(self, *args, **kwargs):
        """docstring for run_tests"""
        res = super(ConsoleReportCoverageRunner, self).run_tests( *args, **kwargs)
        self.cov.report(self.modules.values(), show_missing=1)

        if self.excludes:
            print >> sys.stdout
            print >> sys.stdout, _("The following packages or modules were excluded:"),
            for e in self.excludes:
                print >> sys.stdout, e,
            print >>sys.stdout
        if self.errors:
            print >> sys.stdout
            print >> sys.stderr, _("There were problems with the following packages or modules:"),
            for e in self.errors:
                print >> sys.stderr, e,
            print >> sys.stdout
        return res

class ReportingCoverageRunner(BaseCoverageRunner):
    """Runs coverage.py analysis, as well as generating detailed HTML reports."""

    def __init__(self, outdir = None):
        """
        Constructor, overrides BaseCoverageRunner. Sets output directory
        for reports. Parameter or setting.
        """
        super(ReportingCoverageRunner, self).__init__()
        if(outdir):
            self.outdir = outdir
        else:
            # Realistically, we aren't going to ship the entire reporting framework..
            # but for the time being I have left it in.
            self.outdir = getattr(settings, 'COVERAGE_REPORT_HTML_OUTPUT_DIR', 'test_html')
            self.outdir = os.path.abspath(self.outdir)
            # Create directory
            if( not os.path.exists(self.outdir)):
                os.mkdir(self.outdir)


    def run_tests(self, *args, **kwargs):
        """
        Overrides BaseCoverageRunner.run_tests, and adds html report generation
        with the results
        """
        res = super(ReportingCoverageRunner, self).run_tests( *args, **kwargs)
        self.cov.html_report(self.modules.values(),
                                directory=self.outdir,
                                ignore_errors=True,
                                omit_prefixes='modeltests')
        print >>sys.stdout
        print >>sys.stdout, _("HTML reports were output to '%s'") %self.outdir

        return res