From 0b971f635df881220a1c4f6adad11ce867a0004a Mon Sep 17 00:00:00 2001
From: Henrik Levkowetz
Date: Sat, 14 Mar 2015 19:08:37 +0000
Subject: [PATCH] Added test coverage data to the release pages if available
for the release. Added saving of html pages for the code coverage to a
directory in the static files area. If a code coverage report is available,
a link to it will be shown on the release page of the current release.
Renamed some setting variables related to test coverage to be more explicit
and precise. - Legacy-Id: 9201
---
ietf/release/urls.py | 5 ++---
ietf/release/views.py | 35 ++++++++++++++++++++++++++---
ietf/settings.py | 14 +++++++-----
ietf/templates/release/release.html | 20 ++++++++++++++---
ietf/urls.py | 2 +-
ietf/utils/test_runner.py | 9 ++++++--
static/static/coverage/.gitignore | 1 +
7 files changed, 69 insertions(+), 17 deletions(-)
create mode 100644 static/static/coverage/.gitignore
diff --git a/ietf/release/urls.py b/ietf/release/urls.py
index 137deb616..5f6068d8e 100644
--- a/ietf/release/urls.py
+++ b/ietf/release/urls.py
@@ -1,8 +1,7 @@
from django.conf.urls import patterns
urlpatterns = patterns('',
- (r'^$', 'ietf.release.views.release'),
- (r'^(?P.+)/$', 'ietf.release.views.release'),
- (r'^coverage/code/$', 'ietf.release.views.code_coverage')
+ (r'^$', 'ietf.release.views.release'),
+ (r'^(?P[0-9.]+.*)/$', 'ietf.release.views.release'),
)
diff --git a/ietf/release/views.py b/ietf/release/views.py
index dc086b390..825d6e1d2 100644
--- a/ietf/release/views.py
+++ b/ietf/release/views.py
@@ -1,5 +1,7 @@
import os
import re
+import json
+import datetime
from django.template import RequestContext
from django.shortcuts import render_to_response
@@ -30,7 +32,34 @@ def release(request, version=None):
next = entry
entries = dict((entry.version, entry) for entry in log_entries)
if version == None or version not in entries:
- version = log_entries[0].version
- entries[version].logentry = trac_links(entries[version].logentry)
- return render_to_response('release/release.html', { 'releases': log_entries, 'version': version, 'entry': entries[version], }, context_instance=RequestContext(request))
+ version = log_entries[0].version
+ entries[version].logentry = trac_links(entries[version].logentry.strip('\n'))
+ code_coverage_url = None
+ code_coverage_time = None
+ if os.path.exists(settings.TEST_CODE_COVERAGE_REPORT_FILE) and version == log_entries[0].version:
+ code_coverage_url = settings.TEST_CODE_COVERAGE_REPORT_URL
+ code_coverage_time = datetime.datetime.fromtimestamp(os.path.getmtime(settings.TEST_CODE_COVERAGE_REPORT_FILE))
+
+ coverage = {}
+ if os.path.exists(settings.TEST_COVERAGE_MASTER_FILE):
+ with open(settings.TEST_COVERAGE_MASTER_FILE) as file:
+ coverage_data = json.load(file)
+ if version in coverage_data:
+ coverage = coverage_data[version]
+ for key in coverage:
+ if "coverage" in coverage[key]:
+ coverage[key]["percentage"] = coverage[key]["coverage"] * 100
+
+ return render_to_response('release/release.html',
+ {
+ 'releases': log_entries,
+ 'version': version,
+ 'entry': entries[version],
+ 'coverage': coverage,
+ 'code_coverage_url': code_coverage_url,
+ 'code_coverage_time': code_coverage_time,
+ },
+ context_instance=RequestContext(request))
+
+
diff --git a/ietf/settings.py b/ietf/settings.py
index b22e6c6d8..39fa04abb 100644
--- a/ietf/settings.py
+++ b/ietf/settings.py
@@ -289,18 +289,22 @@ TEST_CODE_COVERAGE_EXCLUDE = [
TEST_COVERAGE_MASTER_FILE = "release-coverage.json"
TEST_COVERAGE_LATEST_FILE = "latest-coverage.json"
-
if SERVER_MODE != 'production':
import coverage
- COVERAGE_CHECKER = coverage.coverage(source=[ BASE_DIR ], cover_pylib=False, omit=TEST_CODE_COVERAGE_EXCLUDE)
- if len(COVERAGE_CHECKER.collector._collectors) == 0:
- COVERAGE_CHECKER.start()
+ TEST_CODE_COVERAGE_CHECKER = coverage.coverage(source=[ BASE_DIR ], cover_pylib=False, omit=TEST_CODE_COVERAGE_EXCLUDE)
+ if len(TEST_CODE_COVERAGE_CHECKER.collector._collectors) == 0:
+ TEST_CODE_COVERAGE_CHECKER.start()
+
+TEST_CODE_COVERAGE_REPORT_PATH = "static/coverage/"
+TEST_CODE_COVERAGE_REPORT_URL = os.path.join(STATIC_URL, TEST_CODE_COVERAGE_REPORT_PATH, "index.html")
+TEST_CODE_COVERAGE_REPORT_DIR = os.path.join(STATIC_ROOT, TEST_CODE_COVERAGE_REPORT_PATH)
+TEST_CODE_COVERAGE_REPORT_FILE = os.path.join(TEST_CODE_COVERAGE_REPORT_DIR, "index.html")
# WG Chair configuration
MAX_WG_DELEGATES = 3
DATE_FORMAT = "Y-m-d"
-DATETIME_FORMAT = "Y-m-d H:i"
+DATETIME_FORMAT = "Y-m-d H:i T"
# Override this in settings_local.py if needed
# *_PATH variables ends with a slash/ .
diff --git a/ietf/templates/release/release.html b/ietf/templates/release/release.html
index eaf23b320..4d1d53a71 100644
--- a/ietf/templates/release/release.html
+++ b/ietf/templates/release/release.html
@@ -10,16 +10,30 @@
|
{% if entry.next %}next release →{% else %}next release →{% endif %}
+
- Release Notes:
+ {% if coverage %}
+ Tested:
+ Code: {{coverage.code.percentage|stringformat:".2f"}}%,
+ Templates: {{coverage.template.percentage|stringformat:".2f"}}%,
+ URLs: {{coverage.url.percentage|stringformat:".2f"}}%
+ {% endif %}
+ {% if code_coverage_url %}
+
+ (A code test coverage report dated {{code_coverage_time}} is available.)
+ {% endif %}
+
+
+
+
+
+
Release Notes:
{{entry.logentry|safe}}
-
-
Release list:
diff --git a/ietf/urls.py b/ietf/urls.py
index 05e0cd5a7..34ccd3fc2 100644
--- a/ietf/urls.py
+++ b/ietf/urls.py
@@ -74,7 +74,7 @@ for n,a in api._api_list:
if settings.SERVER_MODE in ('development', 'test'):
urlpatterns += patterns('',
- (r'^(?P(?:images|css|js|test)/.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
+ (r'^(?P(?:images|css|js|test|static)/.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
(r'^(?Padmin/(?:img|css|js)/.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
(r'^(?Psecretariat/(img|css|js)/.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
(r'^(?Probots\.txt)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT+"dev/"}),
diff --git a/ietf/utils/test_runner.py b/ietf/utils/test_runner.py
index 414249dc2..7c991cffb 100644
--- a/ietf/utils/test_runner.py
+++ b/ietf/utils/test_runner.py
@@ -283,10 +283,15 @@ class CoverageTest(TestCase):
include = [ os.path.join(path, '*') for path in self.runner.test_paths ]
checker = self.runner.code_coverage_checker
checker.stop()
+ # Save to the .coverage file
checker.save()
- checker._harvest_data()
+ # Apply the confirured and requested omit and include data
checker.config.from_args(ignore_errors=None, omit=settings.TEST_CODE_COVERAGE_EXCLUDE,
include=include, file=None)
+ # Maybe output a html report
+ if self.runner.run_full_test_suite:
+ checker.html_report(directory=settings.TEST_CODE_COVERAGE_REPORT_DIR)
+ # In any case, build a dictionary with per-file data for this run
reporter = CoverageReporter(checker, checker.config)
self.runner.coverage_data["code"] = reporter.report()
self.report_test_result("code")
@@ -340,7 +345,7 @@ class IetfTestRunner(DiscoverRunner):
settings.TEMPLATE_LOADERS = ('ietf.utils.test_runner.template_coverage_loader',) + settings.TEMPLATE_LOADERS
settings.MIDDLEWARE_CLASSES = ('ietf.utils.test_runner.RecordUrlsMiddleware',) + settings.MIDDLEWARE_CLASSES
- self.code_coverage_checker = settings.COVERAGE_CHECKER
+ self.code_coverage_checker = settings.TEST_CODE_COVERAGE_CHECKER
if settings.SITE_ID != 1:
print " Changing SITE_ID to '1' during testing."
diff --git a/static/static/coverage/.gitignore b/static/static/coverage/.gitignore
new file mode 100644
index 000000000..33662f554
--- /dev/null
+++ b/static/static/coverage/.gitignore
@@ -0,0 +1 @@
+/*