summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2016-01-07 20:07:04 -0500
committerNed Batchelder <ned@nedbatchelder.com>2016-01-07 20:07:04 -0500
commitb7035114aa515d9d1fe171a9bf678868e76d8f74 (patch)
tree60609f38079b9de18cdbee1d255e96e9c666dd31 /tests
parentd1c92d8e6b066a7b16d625b566853821afe8b46c (diff)
parentd93ddb9524a3e3535541812bbeade8e8ff822409 (diff)
downloadpython-coveragepy-git-b7035114aa515d9d1fe171a9bf678868e76d8f74.tar.gz
Branch analysis is now done with AST instead of bytecode
Diffstat (limited to 'tests')
-rw-r--r--tests/coveragetest.py26
-rw-r--r--tests/test_arcs.py566
-rw-r--r--tests/test_backward.py3
-rw-r--r--tests/test_coverage.py100
-rw-r--r--tests/test_parser.py2
-rw-r--r--tests/test_summary.py6
-rw-r--r--tests/test_testing.py43
7 files changed, 640 insertions, 106 deletions
diff --git a/tests/coveragetest.py b/tests/coveragetest.py
index 3468b794..d79aee7f 100644
--- a/tests/coveragetest.py
+++ b/tests/coveragetest.py
@@ -20,6 +20,7 @@ from coverage.cmdline import CoverageScript
from coverage.debug import _TEST_NAME_FILE, DebugControl
from coverage.test_helpers import (
EnvironmentAwareMixin, StdStreamCapturingMixin, TempDirMixin,
+ DelayedAssertionMixin,
)
from nose.plugins.skip import SkipTest
@@ -35,6 +36,7 @@ class CoverageTest(
EnvironmentAwareMixin,
StdStreamCapturingMixin,
TempDirMixin,
+ DelayedAssertionMixin,
TestCase
):
"""A base class for coverage.py test cases."""
@@ -163,7 +165,7 @@ class CoverageTest(
def check_coverage(
self, text, lines=None, missing="", report="",
excludes=None, partials="",
- arcz=None, arcz_missing=None, arcz_unpredicted=None,
+ arcz=None, arcz_missing="", arcz_unpredicted="",
arcs=None, arcs_missing=None, arcs_unpredicted=None,
):
"""Check the coverage measurement of `text`.
@@ -175,10 +177,11 @@ class CoverageTest(
of the measurement report.
For arc measurement, `arcz` is a string that can be decoded into arcs
- in the code (see `arcz_to_arcs` for the encoding scheme),
+ in the code (see `arcz_to_arcs` for the encoding scheme).
`arcz_missing` are the arcs that are not executed, and
- `arcs_unpredicted` are the arcs executed in the code, but not deducible
- from the code.
+ `arcz_unpredicted` are the arcs executed in the code, but not deducible
+ from the code. These last two default to "", meaning we explicitly
+ check that there are no missing or unpredicted arcs.
Returns the Coverage object, in case you want to poke at it some more.
@@ -191,14 +194,13 @@ class CoverageTest(
if arcs is None and arcz is not None:
arcs = self.arcz_to_arcs(arcz)
- if arcs_missing is None and arcz_missing is not None:
+ if arcs_missing is None:
arcs_missing = self.arcz_to_arcs(arcz_missing)
- if arcs_unpredicted is None and arcz_unpredicted is not None:
+ if arcs_unpredicted is None:
arcs_unpredicted = self.arcz_to_arcs(arcz_unpredicted)
- branch = any(x is not None for x in [arcs, arcs_missing, arcs_unpredicted])
# Start up coverage.py.
- cov = coverage.Coverage(branch=branch)
+ cov = coverage.Coverage(branch=True)
cov.erase()
for exc in excludes or []:
cov.exclude(exc)
@@ -238,15 +240,17 @@ class CoverageTest(
self.fail("None of the missing choices matched %r" % missing_formatted)
if arcs is not None:
- self.assert_equal_args(analysis.arc_possibilities(), arcs, "Possible arcs differ")
+ with self.delayed_assertions():
+ self.assert_equal_args(
+ analysis.arc_possibilities(), arcs,
+ "Possible arcs differ",
+ )
- if arcs_missing is not None:
self.assert_equal_args(
analysis.arcs_missing(), arcs_missing,
"Missing arcs differ"
)
- if arcs_unpredicted is not None:
self.assert_equal_args(
analysis.arcs_unpredicted(), arcs_unpredicted,
"Unpredicted arcs differ"
diff --git a/tests/test_arcs.py b/tests/test_arcs.py
index 18b18fdb..c52bc8aa 100644
--- a/tests/test_arcs.py
+++ b/tests/test_arcs.py
@@ -83,7 +83,8 @@ class SimpleArcTest(CoverageTest):
if len([]) == 0: a = 2
assert a == 2
""",
- arcz=".1 12 23 3.", arcz_missing="")
+ arcz=".1 12 23 3.",
+ )
self.check_coverage("""\
def fn(x):
if x % 2: return True
@@ -102,7 +103,8 @@ class SimpleArcTest(CoverageTest):
b = \\
6
""",
- arcz=".1 15 5-2", arcz_missing="")
+ arcz=".1 15 5-2",
+ )
def test_if_return(self):
self.check_coverage("""\
@@ -114,8 +116,8 @@ class SimpleArcTest(CoverageTest):
x = if_ret(0) + if_ret(1)
assert x == 8
""",
- arcz=".1 16 67 7. .2 23 24 3. 45 5.", arcz_missing=""
- )
+ arcz=".1 16 67 7. .2 23 24 3. 45 5.",
+ )
def test_dont_confuse_exit_and_else(self):
self.check_coverage("""\
@@ -141,15 +143,21 @@ class SimpleArcTest(CoverageTest):
)
def test_unused_lambdas_are_confusing_bug_90(self):
- self.skip("Expected failure: bug 90")
self.check_coverage("""\
a = 1
fn = lambda x: x
b = 3
""",
- arcz=".1 12 .2 2-2 23 3."
+ arcz=".1 12 .2 2-2 23 3.", arcz_missing=".2 2-2",
)
+ def test_what_is_the_sound_of_no_lines_clapping(self):
+ self.check_coverage("""\
+ # __init__.py
+ """,
+ arcz=".1 1.",
+ )
+
class WithTest(CoverageTest):
"""Arc-measuring tests involving context managers."""
@@ -188,7 +196,8 @@ class LoopArcTest(CoverageTest):
a = i
assert a == 9
""",
- arcz=".1 12 21 13 3.", arcz_missing="")
+ arcz=".1 12 21 13 3.",
+ )
self.check_coverage("""\
a = -1
for i in range(0):
@@ -204,7 +213,8 @@ class LoopArcTest(CoverageTest):
a = i + j
assert a == 4
""",
- arcz=".1 12 23 32 21 14 4.", arcz_missing="")
+ arcz=".1 12 23 32 21 14 4.",
+ )
def test_break(self):
self.check_coverage("""\
@@ -267,7 +277,7 @@ class LoopArcTest(CoverageTest):
assert a == 4 and i == 3
""",
arcz=arcz,
- )
+ )
def test_for_if_else_for(self):
self.check_coverage("""\
@@ -311,6 +321,22 @@ class LoopArcTest(CoverageTest):
arcz=".1 .2 23 32 34 47 26 67 7. 18 89 9."
)
+ def test_while_else(self):
+ self.check_coverage("""\
+ def whileelse(seq):
+ while seq:
+ n = seq.pop()
+ if n > 4:
+ break
+ else:
+ n = 99
+ return n
+ assert whileelse([1, 2]) == 99
+ assert whileelse([1, 5]) == 5
+ """,
+ arcz=".1 19 9A A. .2 23 34 45 58 42 27 78 8.",
+ )
+
def test_confusing_for_loop_bug_175(self):
if env.PY3:
# Py3 counts the list comp as a separate code object.
@@ -324,7 +350,8 @@ class LoopArcTest(CoverageTest):
x = tup[0]
y = tup[1]
""",
- arcz=arcz, arcz_missing="", arcz_unpredicted="")
+ arcz=arcz,
+ )
if env.PY3:
arcz = ".1 12 .2 2-2 23 34 42 2."
else:
@@ -335,7 +362,92 @@ class LoopArcTest(CoverageTest):
x = tup[0]
y = tup[1]
""",
- arcz=arcz, arcz_missing="", arcz_unpredicted="")
+ arcz=arcz,
+ )
+
+ def test_generator_expression(self):
+ # Generator expression:
+ self.check_coverage("""\
+ o = ((1,2), (3,4))
+ o = (a for a in o)
+ for tup in o:
+ x = tup[0]
+ y = tup[1]
+ """,
+ arcz=".1 .2 2-2 12 23 34 45 53 3.",
+ )
+
+ def test_other_comprehensions(self):
+ if env.PYVERSION < (2, 7):
+ self.skip("Don't have set or dict comprehensions before 2.7")
+ # Set comprehension:
+ self.check_coverage("""\
+ o = ((1,2), (3,4))
+ o = {a for a in o}
+ for tup in o:
+ x = tup[0]
+ y = tup[1]
+ """,
+ arcz=".1 .2 2-2 12 23 34 45 53 3.",
+ )
+ # Dict comprehension:
+ self.check_coverage("""\
+ o = ((1,2), (3,4))
+ o = {a:1 for a in o}
+ for tup in o:
+ x = tup[0]
+ y = tup[1]
+ """,
+ arcz=".1 .2 2-2 12 23 34 45 53 3.",
+ )
+
+ def test_multiline_dict_comp(self):
+ if env.PYVERSION < (2, 7):
+ self.skip("Don't have set or dict comprehensions before 2.7")
+ if env.PYVERSION < (3, 5):
+ arcz = ".2 2B B-4 2-4"
+ else:
+ arcz = ".2 2B B-3 2-3"
+ # Multiline dict comp:
+ self.check_coverage("""\
+ # comment
+ d = \\
+ {
+ i:
+ str(i)
+ for
+ i
+ in
+ range(9)
+ }
+ x = 11
+ """,
+ arcz=arcz,
+ )
+ # Multi dict comp:
+ if env.PYVERSION < (3, 5):
+ arcz = ".2 2F F-4 2-4"
+ else:
+ arcz = ".2 2F F-3 2-3"
+ self.check_coverage("""\
+ # comment
+ d = \\
+ {
+ (i, j):
+ str(i+j)
+ for
+ i
+ in
+ range(9)
+ for
+ j
+ in
+ range(13)
+ }
+ x = 15
+ """,
+ arcz=arcz,
+ )
class ExceptionArcTest(CoverageTest):
@@ -361,44 +473,48 @@ class ExceptionArcTest(CoverageTest):
b = 7
assert a == 3 and b == 7
""",
- arcz=".1 12 23 34 58 67 78 8.",
- arcz_missing="58", arcz_unpredicted="46")
+ arcz=".1 12 23 34 46 58 67 78 8.",
+ arcz_missing="58",
+ )
def test_hidden_raise(self):
self.check_coverage("""\
a, b = 1, 1
def oops(x):
- if x % 2: raise Exception("odd")
+ if x % 2:
+ raise Exception("odd")
try:
- a = 5
+ a = 6
oops(1)
- a = 7
+ a = 8
except:
- b = 9
- assert a == 5 and b == 9
+ b = 10
+ assert a == 6 and b == 10
""",
- arcz=".1 12 .3 3-2 24 45 56 67 7A 89 9A A.",
- arcz_missing="67 7A", arcz_unpredicted="68")
+ arcz=".1 12 .3 34 3-2 4-2 25 56 67 78 8B 9A AB B.",
+ arcz_missing="3-2 78 8B", arcz_unpredicted="79",
+ )
def test_except_with_type(self):
self.check_coverage("""\
a, b = 1, 1
def oops(x):
- if x % 2: raise ValueError("odd")
+ if x % 2:
+ raise ValueError("odd")
def try_it(x):
try:
- a = 6
+ a = 7
oops(x)
- a = 8
+ a = 9
except ValueError:
- b = 10
+ b = 11
return a
- assert try_it(0) == 8 # C
- assert try_it(1) == 6 # D
+ assert try_it(0) == 9 # C
+ assert try_it(1) == 7 # D
""",
- arcz=".1 12 .3 3-2 24 4C CD D. .5 56 67 78 8B 9A AB B-4",
- arcz_missing="",
- arcz_unpredicted="79")
+ arcz=".1 12 .3 34 3-2 4-2 25 5D DE E. .6 67 78 89 9C AB BC C-5",
+ arcz_unpredicted="8A",
+ )
def test_try_finally(self):
self.check_coverage("""\
@@ -409,7 +525,8 @@ class ExceptionArcTest(CoverageTest):
c = 5
assert a == 3 and c == 5
""",
- arcz=".1 12 23 35 56 6.", arcz_missing="")
+ arcz=".1 12 23 35 56 6.",
+ )
self.check_coverage("""\
a, c, d = 1, 1, 1
try:
@@ -421,8 +538,9 @@ class ExceptionArcTest(CoverageTest):
d = 8
assert a == 4 and c == 6 and d == 1 # 9
""",
- arcz=".1 12 23 34 46 67 78 89 69 9.",
- arcz_missing="67 78 89", arcz_unpredicted="")
+ arcz=".1 12 23 34 46 78 89 69 9.",
+ arcz_missing="78 89",
+ )
self.check_coverage("""\
a, c, d = 1, 1, 1
try:
@@ -436,8 +554,9 @@ class ExceptionArcTest(CoverageTest):
d = 10 # A
assert a == 4 and c == 8 and d == 10 # B
""",
- arcz=".1 12 23 34 45 68 89 8B 9A AB B.",
- arcz_missing="68 8B", arcz_unpredicted="58")
+ arcz=".1 12 23 34 45 58 68 89 8B 9A AB B.",
+ arcz_missing="68 8B",
+ )
def test_finally_in_loop(self):
self.check_coverage("""\
@@ -455,8 +574,9 @@ class ExceptionArcTest(CoverageTest):
d = 12 # C
assert a == 5 and c == 10 and d == 12 # D
""",
- arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB BC CD D.",
- arcz_missing="3D", arcz_unpredicted="7A")
+ arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AB BC CD D.",
+ arcz_missing="3D",
+ )
self.check_coverage("""\
a, c, d, i = 1, 1, 1, 99
try:
@@ -472,11 +592,12 @@ class ExceptionArcTest(CoverageTest):
d = 12 # C
assert a == 8 and c == 10 and d == 1 # D
""",
- arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB BC CD D.",
- arcz_missing="67 AB BC CD", arcz_unpredicted="")
+ arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AB BC CD D.",
+ arcz_missing="67 7A AB BC CD",
+ )
- def test_break_in_finally(self):
+ def test_break_through_finally(self):
self.check_coverage("""\
a, c, d, i = 1, 1, 1, 99
try:
@@ -492,8 +613,29 @@ class ExceptionArcTest(CoverageTest):
d = 12 # C
assert a == 5 and c == 10 and d == 1 # D
""",
- arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AB BC CD D.",
- arcz_missing="3D AB BC CD", arcz_unpredicted="AD")
+ arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AD BC CD D.",
+ arcz_missing="3D BC CD",
+ )
+
+ def test_continue_through_finally(self):
+ self.check_coverage("""\
+ a, b, c, d, i = 1, 1, 1, 1, 99
+ try:
+ for i in range(5):
+ try:
+ a = 5
+ if i > 0:
+ continue
+ b = 8
+ finally:
+ c = 10
+ except:
+ d = 12 # C
+ assert (a, b, c, d) == (5, 8, 10, 1) # D
+ """,
+ arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 BC CD D.",
+ arcz_missing="BC CD",
+ )
def test_finally_in_loop_bug_92(self):
self.check_coverage("""\
@@ -506,14 +648,10 @@ class ExceptionArcTest(CoverageTest):
h = 7
""",
arcz=".1 12 23 35 56 61 17 7.",
- arcz_missing="", arcz_unpredicted="")
+ )
# "except Exception as e" is crucial here.
def test_bug_212(self):
- # Run this test only on Py2 for now. I hope to fix it on Py3
- # eventually...
- if env.PY3:
- self.skip("This doesn't work on Python 3")
self.check_coverage("""\
def b(exc):
try:
@@ -530,8 +668,8 @@ class ExceptionArcTest(CoverageTest):
except:
pass
""",
- arcz=".1 .2 1A 23 34 56 67 68 8. AB BC C. DE E.",
- arcz_missing="C.", arcz_unpredicted="45 7. CD")
+ arcz=".1 .2 1A 23 34 45 56 67 68 7. 8. AB BC C. DE E.",
+ arcz_missing="C.", arcz_unpredicted="CD")
def test_except_finally(self):
self.check_coverage("""\
@@ -562,6 +700,89 @@ class ExceptionArcTest(CoverageTest):
arcz=".1 12 .3 3-2 24 45 56 67 7B 89 9B BC C.",
arcz_missing="67 7B", arcz_unpredicted="68")
+ def test_multiple_except_clauses(self):
+ self.check_coverage("""\
+ a, b, c = 1, 1, 1
+ try:
+ a = 3
+ except ValueError:
+ b = 5
+ except IndexError:
+ a = 7
+ finally:
+ c = 9
+ assert a == 3 and b == 1 and c == 9
+ """,
+ arcz=".1 12 23 45 46 39 59 67 79 69 9A A.",
+ arcz_missing="45 59 46 67 79 69",
+ )
+ self.check_coverage("""\
+ a, b, c = 1, 1, 1
+ try:
+ a = int("xyz") # ValueError
+ except ValueError:
+ b = 5
+ except IndexError:
+ a = 7
+ finally:
+ c = 9
+ assert a == 1 and b == 5 and c == 9
+ """,
+ arcz=".1 12 23 45 46 69 39 59 67 79 9A A.",
+ arcz_missing="39 46 67 79 69",
+ arcz_unpredicted="34",
+ )
+ self.check_coverage("""\
+ a, b, c = 1, 1, 1
+ try:
+ a = [1][3] # IndexError
+ except ValueError:
+ b = 5
+ except IndexError:
+ a = 7
+ finally:
+ c = 9
+ assert a == 7 and b == 1 and c == 9
+ """,
+ arcz=".1 12 23 45 46 39 59 67 79 69 9A A.",
+ arcz_missing="39 45 59 69",
+ arcz_unpredicted="34",
+ )
+ self.check_coverage("""\
+ a, b, c = 1, 1, 1
+ try:
+ try:
+ a = 4/0 # ZeroDivisionError
+ except ValueError:
+ b = 6
+ except IndexError:
+ a = 8
+ finally:
+ c = 10
+ except ZeroDivisionError:
+ pass
+ assert a == 1 and b == 1 and c == 10
+ """,
+ arcz=".1 12 23 34 4A 56 6A 57 78 8A 7A AD BC CD D.",
+ arcz_missing="4A 56 6A 78 8A AD",
+ arcz_unpredicted="45 AB",
+ )
+
+ def test_return_finally(self):
+ self.check_coverage("""\
+ a = [1]
+ def func():
+ try:
+ return 10
+ finally:
+ a.append(6)
+
+ assert func() == 10
+ assert a == [1, 6]
+ """,
+ arcz=".1 12 28 89 9. .3 34 46 6-2",
+ )
+
class YieldTest(CoverageTest):
"""Arc tests for generators."""
@@ -575,8 +796,7 @@ class YieldTest(CoverageTest):
list(gen([1,2,3]))
""",
arcz=".1 .2 23 2. 32 15 5.",
- arcz_missing="",
- arcz_unpredicted="")
+ )
def test_padded_yield_in_loop(self):
self.check_coverage("""\
@@ -591,8 +811,7 @@ class YieldTest(CoverageTest):
list(gen([1,2,3]))
""",
arcz=".1 19 9. .2 23 34 45 56 63 37 7.",
- arcz_missing="",
- arcz_unpredicted="")
+ )
def test_bug_308(self):
self.check_coverage("""\
@@ -604,8 +823,7 @@ class YieldTest(CoverageTest):
print(f())
""",
arcz=".1 15 56 65 5. .2 23 32 2. .3 3-3",
- arcz_missing="",
- arcz_unpredicted="")
+ )
self.check_coverage("""\
def run():
@@ -617,8 +835,7 @@ class YieldTest(CoverageTest):
print(f())
""",
arcz=".1 16 67 76 6. .2 23 34 43 3. 2-2 .4 4-4",
- arcz_missing="",
- arcz_unpredicted="")
+ )
self.check_coverage("""\
def run():
@@ -628,8 +845,7 @@ class YieldTest(CoverageTest):
print(f())
""",
arcz=".1 14 45 54 4. .2 2. 2-2",
- arcz_missing="",
- arcz_unpredicted="")
+ )
def test_bug_324(self):
# This code is tricky: the list() call pulls all the values from gen(),
@@ -647,12 +863,12 @@ class YieldTest(CoverageTest):
".2 23 32 2. " # The gen() function
".3 3-3", # The generator expression
arcz_missing=".3 3-3",
- arcz_unpredicted="")
+ )
def test_coroutines(self):
self.check_coverage("""\
def double_inputs():
- while [1]: # avoid compiler differences
+ while len([1]): # avoid compiler differences
x = yield
x *= 2
yield x
@@ -667,9 +883,26 @@ class YieldTest(CoverageTest):
".1 17 78 89 9A AB B. "
".2 23 34 45 52 2.",
arcz_missing="2.",
- arcz_unpredicted="")
+ )
self.assertEqual(self.stdout(), "20\n12\n")
+ def test_yield_from(self):
+ if env.PYVERSION < (3, 3):
+ self.skip("Python before 3.3 doesn't have 'yield from'")
+ self.check_coverage("""\
+ def gen(inp):
+ i = 2
+ for n in inp:
+ i = 4
+ yield from range(3)
+ i = 6
+ i = 7
+
+ list(gen([1,2,3]))
+ """,
+ arcz=".1 19 9. .2 23 34 45 56 5. 63 37 7.",
+ )
+
class MiscArcTest(CoverageTest):
"""Miscellaneous arc-measuring tests."""
@@ -691,29 +924,222 @@ class MiscArcTest(CoverageTest):
}
assert d
""",
- arcz=arcz)
+ arcz=arcz,
+ )
+ self.check_coverage("""\
+ d = \\
+ { 'a': 2,
+ 'b': 3,
+ 'c': {
+ 'd': 5,
+ 'e': 6,
+ }
+ }
+ assert d
+ """,
+ arcz=".1 19 9-2",
+ )
def test_pathologically_long_code_object(self):
# https://bitbucket.org/ned/coveragepy/issue/359
- # The structure of this file is such that an EXTENDED_ARG byte code is
+ # The structure of this file is such that an EXTENDED_ARG bytecode is
# needed to encode the jump at the end. We weren't interpreting those
# opcodes.
+ # Note that we no longer interpret bytecode at all, but it couldn't
+ # hurt to keep the test...
code = """\
data = [
""" + "".join("""\
- [{i}, {i}, {i}, {i}, {i}, {i}, {i}, {i}, {i}, {i}],
+ [
+ {i}, {i}, {i}, {i}, {i}, {i}, {i}, {i}, {i}, {i}],
""".format(i=i) for i in range(2000)
) + """\
]
- if __name__ == "__main__":
- print(len(data))
+ print(len(data))
"""
self.check_coverage(
code,
- arcs=[(-1, 1), (1, 2004), (2004, -2), (2004, 2005), (2005, -2)],
+ arcs=[(-1, 1), (1, 4004), (4004, -3)],
+ arcs_missing=[], arcs_unpredicted=[],
)
+ def test_optimized_away_lines(self):
+ self.skip("TODO: fix this test")
+ self.check_coverage("""\
+ a = 1
+ if len([2]):
+ c = 3
+ if 0: # this line isn't in the compiled code.
+ if len([5]):
+ d = 6
+ e = 7
+ """,
+ lines=[1, 2, 3, 7],
+ arcz=".1 12 23 27 37 7.",
+ )
+
+
+class DecoractorArcTest(CoverageTest):
+ """Tests of arcs with decorators."""
+
+ def test_function_decorator(self):
+ self.check_coverage("""\
+ def decorator(arg):
+ def _dec(f):
+ return f
+ return _dec
+
+ @decorator(6)
+ @decorator(
+ len([8]),
+ )
+ def my_function(
+ a=len([11]),
+ ):
+ x = 13
+ a = 14
+ my_function()
+ """,
+ arcz=
+ ".1 16 67 7A AE EF F. " # main line
+ ".2 24 4. .3 3-2 " # decorators
+ ".D D-6 ", # my_function
+ )
+
+ def test_class_decorator(self):
+ self.check_coverage("""\
+ def decorator(arg):
+ def _dec(c):
+ return c
+ return _dec
+
+ @decorator(6)
+ @decorator(
+ len([8]),
+ )
+ class MyObject(
+ object
+ ):
+ X = 13
+ a = 14
+ """,
+ arcz=
+ ".1 16 67 6D 7A AE E. " # main line
+ ".2 24 4. .3 3-2 " # decorators
+ ".6 D-6 ", # MyObject
+ )
+
+
+class LambdaArcTest(CoverageTest):
+ """Tests of lambdas"""
+
+ def test_lambda(self):
+ self.check_coverage("""\
+ fn = (lambda x:
+ x + 2
+ )
+ assert fn(4) == 6
+ """,
+ arcz=".1 14 4-1 1-1",
+ )
+ self.check_coverage("""\
+
+ fn = \\
+ (
+ lambda
+ x:
+ x
+ +
+ 8
+ )
+ assert fn(10) == 18
+ """,
+ arcz=".2 2A A-4 2-4",
+ )
+
+
+class AsyncTest(CoverageTest):
+ """Tests of the new async and await keywords in Python 3.5"""
+
+ def setUp(self):
+ if env.PYVERSION < (3, 5):
+ self.skip("Async features are new in Python 3.5")
+ super(AsyncTest, self).setUp()
+
+ def test_async(self):
+ self.check_coverage("""\
+ import asyncio
+
+ async def compute(x, y): # 3
+ print("Compute %s + %s ..." % (x, y))
+ await asyncio.sleep(0.001)
+ return x + y # 6
+
+ async def print_sum(x, y): # 8
+ result = (0 +
+ await compute(x, y) # A
+ )
+ print("%s + %s = %s" % (x, y, result))
+
+ loop = asyncio.get_event_loop() # E
+ loop.run_until_complete(print_sum(1, 2))
+ loop.close() # G
+ """,
+ arcz=
+ ".1 13 38 8E EF FG G. "
+ ".4 45 56 5-3 6-3 "
+ ".9 9-8 9C C-8",
+ )
+ self.assertEqual(self.stdout(), "Compute 1 + 2 ...\n1 + 2 = 3\n")
+
+ def test_async_for(self):
+ self.check_coverage("""\
+ import asyncio
+
+ class AsyncIteratorWrapper: # 3
+ def __init__(self, obj): # 4
+ self._it = iter(obj)
+
+ async def __aiter__(self): # 7
+ return self
+
+ async def __anext__(self): # A
+ try:
+ return next(self._it)
+ except StopIteration:
+ raise StopAsyncIteration
+
+ async def doit(): # G
+ async for letter in AsyncIteratorWrapper("abc"):
+ print(letter)
+ print(".")
+
+ loop = asyncio.get_event_loop() # L
+ loop.run_until_complete(doit())
+ loop.close()
+ """,
+ arcz=
+ ".1 13 3G GL LM MN N. " # module main line
+ ".3 34 47 7A A-3 " # class definition
+ ".H HI IH HJ J-G " # doit
+ ".5 5-4 " # __init__
+ ".8 8-7 " # __aiter__
+ ".B BC C-A DE E-A ", # __anext__
+ arcz_unpredicted="CD",
+ )
+ self.assertEqual(self.stdout(), "a\nb\nc\n.\n")
+
+ def test_async_with(self):
+ self.check_coverage("""\
+ async def go():
+ async with x:
+ pass
+ """,
+ arcz=".1 1. .2 23 3.",
+ arcz_missing=".2 23 3.",
+ )
+
class ExcludeTest(CoverageTest):
"""Tests of exclusions to indicate known partial branches."""
@@ -732,7 +1158,8 @@ class ExcludeTest(CoverageTest):
f = 9
""",
[1,2,3,4,5,6,7,8,9],
- arcz=".1 12 23 24 34 45 56 57 67 78 89 9. 8.", arcz_missing="")
+ arcz=".1 12 23 24 34 45 56 57 67 78 89 9. 8.",
+ )
def test_custom_pragmas(self):
self.check_coverage("""\
@@ -744,7 +1171,8 @@ class ExcludeTest(CoverageTest):
""",
[1,2,3,4,5],
partials=["only some"],
- arcz=".1 12 23 34 45 25 5.", arcz_missing="")
+ arcz=".1 12 23 34 45 25 5.",
+ )
class LineDataTest(CoverageTest):
diff --git a/tests/test_backward.py b/tests/test_backward.py
index fbb9ad8b..bbecb780 100644
--- a/tests/test_backward.py
+++ b/tests/test_backward.py
@@ -4,7 +4,7 @@
"""Tests that our version shims in backward.py are working."""
from coverage.backunittest import TestCase
-from coverage.backward import iitems, binary_bytes, byte_to_int, bytes_to_ints
+from coverage.backward import iitems, binary_bytes, bytes_to_ints
class BackwardTest(TestCase):
@@ -20,4 +20,3 @@ class BackwardTest(TestCase):
bb = binary_bytes(byte_values)
self.assertEqual(len(bb), len(byte_values))
self.assertEqual(byte_values, list(bytes_to_ints(bb)))
- self.assertEqual(byte_values, [byte_to_int(b) for b in bb])
diff --git a/tests/test_coverage.py b/tests/test_coverage.py
index 081fe11b..227360e3 100644
--- a/tests/test_coverage.py
+++ b/tests/test_coverage.py
@@ -101,7 +101,7 @@ class BasicCoverageTest(CoverageTest):
# Nothing here
d = 6
""",
- [1,2,4,6], report="4 0 100%")
+ [1,2,4,6], report="4 0 0 0 100%")
def test_indentation_wackiness(self):
# Partial final lines are OK.
@@ -109,7 +109,7 @@ class BasicCoverageTest(CoverageTest):
import sys
if not sys.path:
a = 1
- """,
+ """, # indented last line
[1,2,3], "3")
def test_multiline_initializer(self):
@@ -198,6 +198,21 @@ class SimpleStatementTest(CoverageTest):
""",
[1,2,3], "")
+ def test_more_assignments(self):
+ self.check_coverage("""\
+ x = []
+ d = {}
+ d[
+ 4 + len(x)
+ + 5
+ ] = \\
+ d[
+ 8 ** 2
+ ] = \\
+ 9
+ """,
+ [1, 2, 3], "")
+
def test_attribute_assignment(self):
# Attribute assignment
self.check_coverage("""\
@@ -550,6 +565,15 @@ class SimpleStatementTest(CoverageTest):
""",
([1,3,6,7], [1,3,5,6,7], [1,3,4,5,6,7]), "")
+ def test_nonascii(self):
+ self.check_coverage("""\
+ # coding: utf8
+ a = 2
+ b = 3
+ """,
+ [2, 3]
+ )
+
class CompoundStatementTest(CoverageTest):
"""Testing coverage of multi-line compound statements."""
@@ -618,7 +642,8 @@ class CompoundStatementTest(CoverageTest):
z = 7
assert x == 3
""",
- [1,2,3,4,5,7,8], "4-7", report="7 3 57% 4-7")
+ [1,2,3,4,5,7,8], "4-7", report="7 3 4 1 45% 4-7, 2->4",
+ )
self.check_coverage("""\
a = 1; b = 2; c = 3;
if a != 1:
@@ -629,7 +654,8 @@ class CompoundStatementTest(CoverageTest):
z = 7
assert y == 5
""",
- [1,2,3,4,5,7,8], "3, 7", report="7 2 71% 3, 7")
+ [1,2,3,4,5,7,8], "3, 7", report="7 2 4 2 64% 3, 7, 2->3, 4->7",
+ )
self.check_coverage("""\
a = 1; b = 2; c = 3;
if a != 1:
@@ -640,7 +666,8 @@ class CompoundStatementTest(CoverageTest):
z = 7
assert z == 7
""",
- [1,2,3,4,5,7,8], "3, 5", report="7 2 71% 3, 5")
+ [1,2,3,4,5,7,8], "3, 5", report="7 2 4 2 64% 3, 5, 2->3, 4->5",
+ )
def test_elif_no_else(self):
self.check_coverage("""\
@@ -651,7 +678,8 @@ class CompoundStatementTest(CoverageTest):
y = 5
assert x == 3
""",
- [1,2,3,4,5,6], "4-5", report="6 2 67% 4-5")
+ [1,2,3,4,5,6], "4-5", report="6 2 4 1 50% 4-5, 2->4",
+ )
self.check_coverage("""\
a = 1; b = 2; c = 3;
if a != 1:
@@ -660,7 +688,8 @@ class CompoundStatementTest(CoverageTest):
y = 5
assert y == 5
""",
- [1,2,3,4,5,6], "3", report="6 1 83% 3")
+ [1,2,3,4,5,6], "3", report="6 1 4 2 70% 3, 2->3, 4->6",
+ )
def test_elif_bizarre(self):
self.check_coverage("""\
@@ -1008,7 +1037,10 @@ class CompoundStatementTest(CoverageTest):
a = 123
assert a == 123
""",
- [1,2,3,4,5,7,8], "4-5")
+ [1,2,3,4,5,7,8], "4-5",
+ arcz=".1 12 23 45 58 37 78 8.",
+ arcz_missing="45 58",
+ )
self.check_coverage("""\
a = 0
try:
@@ -1020,7 +1052,10 @@ class CompoundStatementTest(CoverageTest):
a = 123
assert a == 99
""",
- [1,2,3,4,5,6,8,9], "8")
+ [1,2,3,4,5,6,8,9], "8",
+ arcz=".1 12 23 34 45 56 69 89 9.",
+ arcz_missing="89",
+ )
def test_try_finally(self):
self.check_coverage("""\
@@ -1366,7 +1401,10 @@ class ExcludeTest(CoverageTest):
a = 123
assert a == 123
""",
- [1,2,3,7,8], "", excludes=['#pragma: NO COVER'])
+ [1,2,3,7,8], "", excludes=['#pragma: NO COVER'],
+ arcz=".1 12 23 37 45 58 78 8.",
+ arcz_missing="45 58",
+ )
self.check_coverage("""\
a = 0
try:
@@ -1378,7 +1416,10 @@ class ExcludeTest(CoverageTest):
a = 123
assert a == 99
""",
- [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER'])
+ [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER'],
+ arcz=".1 12 23 34 45 56 69 89 9.",
+ arcz_missing="89",
+ )
def test_excluding_try_except_pass(self):
self.check_coverage("""\
@@ -1412,7 +1453,10 @@ class ExcludeTest(CoverageTest):
a = 123
assert a == 123
""",
- [1,2,3,7,8], "", excludes=['#pragma: NO COVER'])
+ [1,2,3,7,8], "", excludes=['#pragma: NO COVER'],
+ arcz=".1 12 23 37 45 58 78 8.",
+ arcz_missing="45 58",
+ )
self.check_coverage("""\
a = 0
try:
@@ -1424,7 +1468,10 @@ class ExcludeTest(CoverageTest):
x = 2
assert a == 99
""",
- [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER'])
+ [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER'],
+ arcz=".1 12 23 34 45 56 69 89 9.",
+ arcz_missing="89",
+ )
def test_excluding_if_pass(self):
# From a comment on the coverage.py page by Michael McNeil Forbes:
@@ -1614,7 +1661,9 @@ class Py25Test(CoverageTest):
b = 2
assert a == 1 and b == 2
""",
- [1,2,3,4,5,7,8], "4-5")
+ [1,2,3,4,5,7,8], "4-5",
+ arcz=".1 12 23 37 45 57 78 8.", arcz_missing="45 57",
+ )
self.check_coverage("""\
a = 0; b = 0
try:
@@ -1626,7 +1675,9 @@ class Py25Test(CoverageTest):
b = 2
assert a == 99 and b == 2
""",
- [1,2,3,4,5,6,8,9], "")
+ [1,2,3,4,5,6,8,9], "",
+ arcz=".1 12 23 34 45 56 68 89 9.",
+ )
self.check_coverage("""\
a = 0; b = 0
try:
@@ -1640,7 +1691,9 @@ class Py25Test(CoverageTest):
b = 2
assert a == 123 and b == 2
""",
- [1,2,3,4,5,6,7,8,10,11], "6")
+ [1,2,3,4,5,6,7,8,10,11], "6",
+ arcz=".1 12 23 34 45 56 57 78 6A 8A AB B.", arcz_missing="56 6A",
+ )
self.check_coverage("""\
a = 0; b = 0
try:
@@ -1656,7 +1709,10 @@ class Py25Test(CoverageTest):
b = 2
assert a == 17 and b == 2
""",
- [1,2,3,4,5,6,7,8,9,10,12,13], "6, 9-10")
+ [1,2,3,4,5,6,7,8,9,10,12,13], "6, 9-10",
+ arcz=".1 12 23 34 45 56 6C 57 78 8C 79 9A AC CD D.",
+ arcz_missing="56 6C 79 9A AC",
+ )
self.check_coverage("""\
a = 0; b = 0
try:
@@ -1669,7 +1725,10 @@ class Py25Test(CoverageTest):
b = 2
assert a == 123 and b == 2
""",
- [1,2,3,4,5,7,9,10], "4-5")
+ [1,2,3,4,5,7,9,10], "4-5",
+ arcz=".1 12 23 37 45 59 79 9A A.",
+ arcz_missing="45 59",
+ )
self.check_coverage("""\
a = 0; b = 0
try:
@@ -1683,7 +1742,10 @@ class Py25Test(CoverageTest):
b = 2
assert a == 99 and b == 2
""",
- [1,2,3,4,5,6,8,10,11], "8")
+ [1,2,3,4,5,6,8,10,11], "8",
+ arcz=".1 12 23 34 45 56 6A 8A AB B.",
+ arcz_missing="8A",
+ )
class ModuleTest(CoverageTest):
diff --git a/tests/test_parser.py b/tests/test_parser.py
index 2a4c88a7..c32fdc4d 100644
--- a/tests/test_parser.py
+++ b/tests/test_parser.py
@@ -72,7 +72,7 @@ class PythonParserTest(CoverageTest):
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
+ 1: 1, 2:1, 3:2, 4:1, 5:2, 6:1, 7:1, 8:1, 9:1
})
def test_excluded_classes(self):
diff --git a/tests/test_summary.py b/tests/test_summary.py
index 56c0b831..9d7a6fe7 100644
--- a/tests/test_summary.py
+++ b/tests/test_summary.py
@@ -607,7 +607,7 @@ class SummaryTest2(CoverageTest):
def test_empty_files(self):
# Shows that empty files like __init__.py are listed as having zero
# statements, not one statement.
- cov = coverage.Coverage()
+ cov = coverage.Coverage(branch=True)
cov.start()
import usepkgs # pragma: nested # pylint: disable=import-error,unused-variable
cov.stop() # pragma: nested
@@ -617,8 +617,8 @@ class SummaryTest2(CoverageTest):
report = repout.getvalue().replace('\\', '/')
report = re.sub(r"\s+", " ", report)
- self.assertIn("tests/modules/pkg1/__init__.py 2 0 100%", report)
- self.assertIn("tests/modules/pkg2/__init__.py 0 0 100%", report)
+ self.assertIn("tests/modules/pkg1/__init__.py 2 0 0 0 100%", report)
+ self.assertIn("tests/modules/pkg2/__init__.py 0 0 0 0 100%", report)
class ReportingReturnValueTest(CoverageTest):
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 9fc7f11d..1dafdd0d 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -6,13 +6,15 @@
import datetime
import os
+import re
import sys
+import textwrap
import coverage
from coverage.backunittest import TestCase
from coverage.backward import to_bytes
from coverage.files import actual_path
-from coverage.test_helpers import EnvironmentAwareMixin, TempDirMixin
+from coverage.test_helpers import EnvironmentAwareMixin, TempDirMixin, DelayedAssertionMixin
from tests.coveragetest import CoverageTest
@@ -97,6 +99,45 @@ class EnvironmentAwareMixinTest(EnvironmentAwareMixin, TestCase):
self.assertNotIn("XYZZY_PLUGH", os.environ)
+class DelayedAssertionMixinTest(DelayedAssertionMixin, TestCase):
+ """Test the `delayed_assertions` method."""
+
+ def test_delayed_assertions(self):
+ # Two assertions can be shown at once:
+ msg = re.escape(textwrap.dedent("""\
+ 2 failed assertions:
+ 'x' != 'y'
+ - x
+ + y
+
+ 'w' != 'z'
+ - w
+ + z
+ """))
+ with self.assertRaisesRegex(AssertionError, msg):
+ with self.delayed_assertions():
+ self.assertEqual("x", "y")
+ self.assertEqual("w", "z")
+
+ # It's also OK if only one fails:
+ msg = re.escape(textwrap.dedent("""\
+ 'w' != 'z'
+ - w
+ + z
+ """))
+ with self.assertRaisesRegex(AssertionError, msg):
+ with self.delayed_assertions():
+ self.assertEqual("x", "x")
+ self.assertEqual("w", "z")
+
+ # If an error happens, it gets reported immediately, no special
+ # handling:
+ with self.assertRaises(ZeroDivisionError):
+ with self.delayed_assertions():
+ self.assertEqual("x", "y")
+ self.assertEqual("w", 1/0)
+
+
class CoverageTestTest(CoverageTest):
"""Test the methods in `CoverageTest`."""