Changed the url coverage code to handle deeper chains of url includes, and to handle url includes through url lists in addition to url modules. Added information in the release coverage dictionaries about the view functions coupled to the urls.

- Legacy-Id: 13706
This commit is contained in:
Henrik Levkowetz 2017-06-22 15:07:06 +00:00
parent 6b69660559
commit f6f0278859
4 changed files with 45 additions and 32 deletions

View file

@ -50,8 +50,8 @@ class Command(BaseCommand):
help='Show absolute figures instead of changes from last release.')
diff_line_format = "%-58s %8s %8s\n"
list_line_format = "%-68s %8s\n"
diff_line_format = "%8s %8s %-58s\n"
list_line_format = "%8s %-68s\n"
valid_sections = ['template', 'url', 'code']
def read_coverage(self, filename, version=None):
@ -109,9 +109,9 @@ class Command(BaseCommand):
else:
raise CommandError("The release coverage data has an unknown format ('%s'), quitting." % mformat)
if lformat == 1:
llines, lcov = None, lcoverage[key]
elif lformat == 2:
llines, lcov = lcoverage[key]
linfo, lcov = None, lcoverage[key]
elif lformat in [2, 4]:
linfo, lcov = lcoverage[key]
else:
raise CommandError("The latest coverage data has an unknown format ('%s'), quitting." % lformat)
@ -124,10 +124,10 @@ class Command(BaseCommand):
if mcov != lcov:
if not header_written:
self.stdout.write(self.diff_line_format %
("\n%s"%section.capitalize(), mversion[:7], lversion[:7]))
self.stdout.write(self.diff_line_format % ("-"*58, "-"*8, "-"*8))
(mversion[:7], lversion[:7], "\n%s"%section.capitalize(), ))
self.stdout.write(self.diff_line_format % ("-"*8, "-"*8, "-"*58))
header_written = True
self.stdout.write(self.diff_line_format % (key, mval, lval))
self.stdout.write(self.diff_line_format % (mval, lval, key, ))
lkey_set = set(lkeys)
rkey_set = set(mkeys)
missing_key_set = rkey_set - lkey_set
@ -156,9 +156,9 @@ class Command(BaseCommand):
for key in keys:
if lformat == 1:
llines, lcov = None, lcoverage[key]
elif lformat == 2:
llines, lcov = lcoverage[key]
linfo, lcov = None, lcoverage[key]
elif lformat in [2, 4]:
linfo, lcov = lcoverage[key]
else:
raise CommandError("The latest coverage data has an unknown format ('%s'), quitting." % lformat)
@ -168,10 +168,10 @@ class Command(BaseCommand):
lval = lcov
if not header_written:
self.stdout.write(self.list_line_format %
("\n%s"%section.capitalize(), lversion[:7]))
self.stdout.write(self.list_line_format % ("-"*58, "-"*8, ))
(lversion[:7], "\n%s"%section.capitalize(), ))
self.stdout.write(self.list_line_format % ("-"*8, "-"*58, ))
header_written = True
self.stdout.write(self.list_line_format % (key, lval))
self.stdout.write(self.list_line_format % (lval, key))
def handle(self, *args, **options):

View file

@ -89,9 +89,9 @@ class CoverageChangeTestCase(TestCase):
os.unlink(latest)
for l in [
r"admin/group/group/change_form.html False True",
r"^api/v1/?$ True False",
r"^community/personal/$ False True",
r"ietf/community/constants - 50.0 %",
r" False True admin/group/group/change_form.html ",
r" True False ^api/v1/?$ ",
r" False True ^community/personal/$ ",
r" - 50.0 % ietf/community/constants ",
]:
self.assertTrue(l in text, msg="Missing line in coverage_change output:\n'%s'\n"%l)

View file

@ -147,18 +147,28 @@ def get_url_patterns(module, apps=None):
if re.search(pat, name):
return True
return False
def append(res, p0, p1, item):
if p1.startswith("^"):
res.append((p0 + p1[1:], item))
else:
res.append((item.p0 + ".*" + p1, item))
if not hasattr(module, 'urlpatterns'):
return []
res = []
for item in module.urlpatterns:
if isinstance(item, RegexURLResolver) and not type(item.urlconf_module) is list:
if include(item.urlconf_module.__name__) and not exclude(item.regex.pattern):
subpatterns = get_url_patterns(item.urlconf_module)
for sub, subitem in subpatterns:
if sub.startswith("^"):
res.append((item.regex.pattern + sub[1:], subitem))
if isinstance(item, RegexURLResolver):
if type(item.urlconf_module) is list:
for subitem in item.urlconf_module:
if isinstance(subitem, RegexURLResolver):
res += get_url_patterns(subitem.urlconf_module)
else:
res.append((item.regex.pattern + ".*" + sub, subitem))
sub = subitem.regex.pattern
append(res, item.regex.pattern, subitem.regex.pattern, subitem)
else:
if include(item.urlconf_module.__name__) and not exclude(item.regex.pattern):
subpatterns = get_url_patterns(item.urlconf_module)
for sub, subitem in subpatterns:
append(res, item.regex.pattern, sub, subitem)
else:
res.append((item.regex.pattern, item))
return res
@ -287,6 +297,7 @@ class CoverageTest(TestCase):
self.runner.coverage_data["template"] = {
"coverage": (1.0*len(covered)/len(all)) if len(all)>0 else float('nan'),
"covered": dict( (k, k in covered) for k in all ),
"format": 1,
}
self.report_test_result("template")
else:
@ -296,30 +307,32 @@ class CoverageTest(TestCase):
if self.runner.check_coverage:
import ietf.urls
url_patterns = get_url_patterns(ietf.urls, self.runner.test_apps)
#debug.pprint('[ r for r,p in url_patterns]')
# skip some patterns that we don't bother with
def ignore_pattern(regex, pattern):
import django.views.static
return (regex in ("^_test500/$", "^accounts/testemail/$")
or regex.startswith("^admin/")
or re.search('^api/v1/[^/]+/[^/]+/', regex)
or getattr(pattern.callback, "__name__", "") == "RedirectView"
or getattr(pattern.callback, "__name__", "") == "TemplateView"
or pattern.callback == django.views.static.serve)
patterns = [(regex, re.compile(regex, re.U)) for regex, pattern in url_patterns
if not ignore_pattern(regex, pattern)]
all = [ regex for regex, compiled in patterns ]
patterns = [(regex, re.compile(regex, re.U), obj) for regex, obj in url_patterns
if not ignore_pattern(regex, obj)]
covered = set()
for url in visited_urls:
for regex, compiled in patterns:
for regex, compiled, obj in patterns:
if regex not in covered and compiled.match(url[1:]): # strip leading /
covered.add(regex)
break
self.runner.coverage_data["url"] = {
"coverage": 1.0*len(covered)/len(all),
"covered": dict( (k, k in covered) for k in all ),
"coverage": 1.0*len(covered)/len(patterns),
"covered": dict( (k, (o.lookup_str, k in covered)) for k,p,o in patterns ),
"format": 4,
}
self.report_test_result("url")
@ -475,7 +488,7 @@ class IetfTestRunner(DiscoverRunner):
"url": {
"coverage": 0.0,
"covered": {},
"format": 1,
"format": 4,
},
"code": {
"coverage": 0.0,

Binary file not shown.