如何在单个HTML文件中获取Django覆盖率报告
我正在运行我的单元测试,并想生成一个 HTML 格式的覆盖率报告。
我知道有一个命令
coverage html --include=myproject/*.*
这个命令会在我的项目目录下生成一个叫 'htmlcov' 的文件夹,里面有所有应用程序和文件的覆盖率报告,都是以 HTML 格式单独存放的。但我只想要一个 HTML 文件(或者说是 'htmlcov' 文件夹里的 index.html 文件),这个文件能给我整个项目的覆盖率。我不想生成所有的文件。请问怎么用 coverage 来做到这一点?或者有没有其他好的方法可以让我生成一个单独的 HTML 文件作为我的单元测试覆盖率报告?
1 个回答
2
我已经基本完成了这个功能的实现。现在这个功能和coverage html
的输出关系很紧密。它是非破坏性的,也就是说,它不会对其他文件造成影响。不过,如果你恰好有一个文件叫htmlcov/coverage.html
,那么这个功能会把它覆盖掉。
import codecs
import os
from bs4 import BeautifulSoup
scripts = []
styles = []
bodies = []
processed = []
def explode(filename):
# We want to turn the body element into a div so we can use it
# in one page with all of the other body elements.
processed.append(filename)
soup = BeautifulSoup(codecs.open(filename, encoding='utf-8'))
body = soup.body
body.name = 'div'
body['id'] = filename
body['class'] = 'body'
bodies.append(body)
# Ensure that we grab all of the scripts that are required by
# this page.
for script in soup.find_all('script'):
if 'src' in script.attrs:
content = codecs.open(script['src'], encoding='utf-8').read()
else:
content = script.string
if content not in scripts:
scripts.append(content)
# Likewise for the link[stylesheet] elements.
for link in soup.find_all('link'):
content = codecs.open(link['href'], encoding='utf-8').read()
if content not in styles:
styles.append(content)
for a in soup.find_all('a'):
# Make sure all local-links are rewritten to point to a more
# fully-qualified name (these are line number links).
if a['href'][0] == '#':
anchor = u'{}-{}'.format(filename, a['href'][1:])
a['href'] = u'#{}'.format(anchor)
a.parent['id'] = anchor
elif a['href'] in processed:
# Pages we have already seen, we want to have a local link.
a['href'] = u'#{}'.format(a['href'])
else:
# Otherwise, we want to see if we have a file that matches
# the href, and embed that. Yay recursion.
try:
explode(a['href'])
except IOError:
pass
else:
a['href'] = u'#{}'.format(a['href'])
TEMPLATE = u'''<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<title>Coverage report</title>
<style>{styles}</style>
<script>{scripts}</script>
</head>
<body>
{body}
</body>
</html>
'''
# Fire off the tree walking with htmlcov/index.html
os.chdir('htmlcov')
explode('index.html')
# Override the toggle_lines function to limit it to just our code block.
scripts.append('''
coverage.toggle_lines = function (btn, cls) {
btn = $(btn);
var hide = "hide_"+cls;
if (btn.hasClass(hide)) {
btn.closest('.body').find("#source ."+cls).removeClass(hide);
btn.removeClass(hide);
}
else {
$("#source ."+cls).addClass(hide);
btn.addClass(hide);
}
};
''')
result = TEMPLATE.format(
styles=u'\n'.join(styles),
scripts=u'\n'.join(scripts),
body=u'\n'.join([unicode(x) for x in bodies])
)
codecs.open('coverage.html', 'w', encoding='utf-8').write(result)
os.chdir('..')