blob: 244d4c700d2ceb5e751de6daf71e540b3779ae96 [file] [log] [blame]
"""Tests for Coverage.py's code parsing."""
import textwrap
from tests.coveragetest import CoverageTest
from coverage.parser import PythonParser
class PythonParserTest(CoverageTest):
"""Tests for Coverage.py's Python code parsing."""
run_in_temp_dir = False
def parse_source(self, text):
"""Parse `text` as source, and return the `PythonParser` used."""
text = textwrap.dedent(text)
parser = PythonParser(text=text, exclude="nocover")
parser.parse_source()
return parser
def test_exit_counts(self):
parser = self.parse_source("""\
# check some basic branch counting
class Foo:
def foo(self, a):
if a:
return 5
else:
return 7
class Bar:
pass
""")
self.assertEqual(parser.exit_counts(), {
2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1
})
def test_try_except(self):
parser = self.parse_source("""\
try:
a = 2
except ValueError:
a = 4
except ZeroDivideError:
a = 6
except:
a = 8
b = 9
""")
self.assertEqual(parser.exit_counts(), {
1: 1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1
})
def test_excluded_classes(self):
parser = self.parse_source("""\
class Foo:
def __init__(self):
pass
if 0: # nocover
class Bar:
pass
""")
self.assertEqual(parser.exit_counts(), {
1:0, 2:1, 3:1
})
def test_missing_branch_to_excluded_code(self):
parser = self.parse_source("""\
if fooey:
a = 2
else: # nocover
a = 4
b = 5
""")
self.assertEqual(parser.exit_counts(), { 1:1, 2:1, 5:1 })
parser = self.parse_source("""\
def foo():
if fooey:
a = 3
else:
a = 5
b = 6
""")
self.assertEqual(parser.exit_counts(), { 1:1, 2:2, 3:1, 5:1, 6:1 })
parser = self.parse_source("""\
def foo():
if fooey:
a = 3
else: # nocover
a = 5
b = 6
""")
self.assertEqual(parser.exit_counts(), { 1:1, 2:1, 3:1, 6:1 })
class ParserFileTest(CoverageTest):
"""Tests for Coverage.py's code parsing from files."""
def parse_file(self, filename):
"""Parse `text` as source, and return the `PythonParser` used."""
parser = PythonParser(filename=filename, exclude="nocover")
self.statements, self.excluded = parser.parse_source()
return parser
def test_line_endings(self):
text = """\
# check some basic branch counting
class Foo:
def foo(self, a):
if a:
return 5
else:
return 7
class Bar:
pass
"""
counts = { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 }
name_endings = (("unix", "\n"), ("dos", "\r\n"), ("mac", "\r"))
for fname, newline in name_endings:
fname = fname + ".py"
self.make_file(fname, text, newline=newline)
parser = self.parse_file(fname)
self.assertEqual(parser.exit_counts(), counts)
def test_encoding(self):
self.make_file("encoded.py", """\
coverage = "\xe7\xf6v\xear\xe3g\xe9"
""")
parser = self.parse_file("encoded.py")
self.assertEqual(parser.exit_counts(), {1: 1})
def test_missing_line_ending(self):
# Test that the set of statements is the same even if a final
# multi-line statement has no final newline.
# https://bitbucket.org/ned/coveragepy/issue/293
self.make_file("normal.py", """\
out, err = subprocess.Popen(
[sys.executable, '-c', 'pass'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()
""")
self.parse_file("normal.py")
self.assertEqual(self.statements, set([1]))
self.make_file("abrupt.py", """\
out, err = subprocess.Popen(
[sys.executable, '-c', 'pass'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).communicate()""") # no final newline.
# Double-check that some test helper wasn't being helpful.
with open("abrupt.py") as f:
self.assertEqual(f.read()[-1], ")")
self.parse_file("abrupt.py")
self.assertEqual(self.statements, set([1]))