summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coverage/control.py8
-rw-r--r--coverage/report.py5
-rw-r--r--coverage/xmlreport.py7
-rw-r--r--test/coveragetest.py29
-rw-r--r--test/test_cmdline.py13
-rw-r--r--test/test_coverage.py26
6 files changed, 68 insertions, 20 deletions
diff --git a/coverage/control.py b/coverage/control.py
index e041cde7..4bcb4ed4 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -304,8 +304,12 @@ class coverage(object):
"""
if outfile:
outfile = open(outfile, "w")
- reporter = XmlReporter(self, ignore_errors)
- reporter.report(morfs, omit_prefixes=omit_prefixes, outfile=outfile)
+ try:
+ reporter = XmlReporter(self, ignore_errors)
+ reporter.report(
+ morfs, omit_prefixes=omit_prefixes, outfile=outfile)
+ finally:
+ outfile.close()
def sysinfo(self):
"""Return a list of key,value pairs showing internal information."""
diff --git a/coverage/report.py b/coverage/report.py
index 7f3e3e02..c2215521 100644
--- a/coverage/report.py
+++ b/coverage/report.py
@@ -2,7 +2,7 @@
import os
from coverage.codeunit import code_unit_factory
-from coverage.misc import NoSource
+from coverage.misc import CoverageException, NoSource
class Reporter(object):
"""A base class for all reporters."""
@@ -45,6 +45,9 @@ class Reporter(object):
"""
self.find_code_units(morfs, omit_prefixes)
+ if not self.code_units:
+ raise CoverageException("No data to report.")
+
self.directory = directory
if self.directory and not os.path.exists(self.directory):
os.makedirs(self.directory)
diff --git a/coverage/xmlreport.py b/coverage/xmlreport.py
index 0fe43712..2e31d9e9 100644
--- a/coverage/xmlreport.py
+++ b/coverage/xmlreport.py
@@ -30,7 +30,6 @@ class XmlReporter(Reporter):
"""
# Initial setup.
outfile = outfile or sys.stdout
- self.find_code_units(morfs, omit_prefixes)
# Create the DOM that will store the data.
impl = xml.dom.minidom.getDOMImplementation()
@@ -39,8 +38,9 @@ class XmlReporter(Reporter):
"http://cobertura.sourceforge.net/xml/coverage-03.dtd"
)
self.xml_out = impl.createDocument(None, "coverage", docType)
+
+ # Write header stuff.
xcoverage = self.xml_out.documentElement
-
xcoverage.setAttribute("version", __version__)
xcoverage.setAttribute("timestamp", str(int(time.time()*1000)))
xcoverage.appendChild(self.xml_out.createComment(
@@ -48,8 +48,9 @@ class XmlReporter(Reporter):
))
xpackages = self.xml_out.createElement("packages")
xcoverage.appendChild(xpackages)
- self.packages = {}
+ # Call xml_file for each file in the data.
+ self.packages = {}
self.report_files(self.xml_file, morfs, omit_prefixes=omit_prefixes)
lnum_tot, lhits_tot = 0, 0
diff --git a/test/coveragetest.py b/test/coveragetest.py
index dffffb29..3c22a0cf 100644
--- a/test/coveragetest.py
+++ b/test/coveragetest.py
@@ -1,6 +1,6 @@
"""Base test case class for coverage testing."""
-import difflib, imp, os, random, re, shutil, sys, tempfile, textwrap, unittest
+import difflib, imp, os, random, re, shlex, shutil, sys, tempfile, textwrap, unittest
import coverage
from coverage.backward import set, sorted, StringIO # pylint: disable-msg=W0622
@@ -20,6 +20,9 @@ class Tee(object):
f.write(data)
+# Status returns for the command line.
+OK, ERR = 0, 1
+
class CoverageTest(unittest.TestCase):
"""A base class for Coverage test cases."""
@@ -253,8 +256,30 @@ class CoverageTest(unittest.TestCase):
fname = os.path.join(*fparts)
return os.path.normcase(os.path.abspath(os.path.realpath(fname)))
+ def command_line(self, args, ret=OK):
+ """Run `args` through the command line.
+
+ Use this when you want to run the full coverage machinery, but in the
+ current process. Exceptions may be thrown from deep in the code.
+ Asserts that `ret` is returned by `CoverageScript.command_line`.
+
+ Compare with `run_command`.
+
+ Returns None.
+
+ """
+ ret_actual = coverage.CoverageScript().command_line(shlex.split(args))
+ self.assertEqual(ret_actual, ret)
+
def run_command(self, cmd):
- """ Run the command-line `cmd`, print its output.
+ """ Run the command-line `cmd` in a subprocess, and print its output.
+
+ Use this when you need to test the process behavior of coverage.
+
+ Compare with `command_line`.
+
+ Returns the process' stdout text.
+
"""
# Add our test modules directory to PYTHONPATH. I'm sure there's too
# much path munging here, but...
diff --git a/test/test_cmdline.py b/test/test_cmdline.py
index 21639cdb..20c9c5d4 100644
--- a/test/test_cmdline.py
+++ b/test/test_cmdline.py
@@ -5,11 +5,9 @@ import mock
import coverage
sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
-from coveragetest import CoverageTest
+from coveragetest import CoverageTest, OK, ERR
-OK, ERR = 0, 1
-
class CmdLineTest(CoverageTest):
"""Tests of execution paths through the command line interpreter."""
@@ -19,15 +17,6 @@ class CmdLineTest(CoverageTest):
.coverage(cover_pylib=None, data_suffix=False, timid=None, branch=None)
.load()\n"""
- def command_line(self, args, ret=OK):
- """Run `args` through the command line.
-
- Checks that `ret` is returned.
-
- """
- ret_actual = coverage.CoverageScript().command_line(shlex.split(args))
- self.assertEqual(ret_actual, ret)
-
def model_object(self):
"""Return a Mock suitable for use in CoverageScript."""
mk = mock.Mock()
diff --git a/test/test_coverage.py b/test/test_coverage.py
index 6544cddd..10cadfef 100644
--- a/test/test_coverage.py
+++ b/test/test_coverage.py
@@ -7,6 +7,8 @@ import os, sys, unittest
import coverage
coverage.use_cache(0)
+from coverage.misc import CoverageException
+
sys.path.insert(0, os.path.split(__file__)[0]) # Force relative import for Py3k
from coveragetest import CoverageTest
@@ -1674,6 +1676,30 @@ class ProcessTest(CoverageTest):
self.assert_matches(out, "No file to run: .*xyzzy.py")
self.assert_("Traceback" not in out)
+ def test_no_data_to_report_on_annotate(self):
+ # Reporting with no data produces a nice message and no output dir.
+ self.assert_raises_msg(
+ CoverageException, "No data to report.",
+ self.command_line, "annotate -d ann"
+ )
+ self.assertFalse(os.path.exists("ann"))
+
+ def test_no_data_to_report_on_html(self):
+ # Reporting with no data produces a nice message and no output dir.
+ self.assert_raises_msg(
+ CoverageException, "No data to report.",
+ self.command_line, "html -d htmlcov"
+ )
+ self.assertFalse(os.path.exists("htmlcov"))
+
+ def test_no_data_to_report_on_xml(self):
+ # Reporting with no data produces a nice message.
+ self.assert_raises_msg(
+ CoverageException, "No data to report.",
+ self.command_line, "xml"
+ )
+ # Currently, this leaves an empty coverage.xml file... :(
+
if __name__ == '__main__':
print("Testing under Python version: %s" % sys.version)