Skip to content

coverage of multiline generator/set/dict comprehensions is wrong when run with pytest's assertion rewriting #515

@nedbat

Description

@nedbat

Originally reported by Andy Freeland (Bitbucket: rouge8, GitHub: rouge8)


Code/config to reproduce available as a gist. Fails on Python 2.7 but not Python 3.5.

Essentially, given this test:

def test_foo():
    # covered!
    assert {i for i in range(10)} == {i for i in range(10)}

    # "didn't finish the set comprehension"
    assert {i for i in range(10)} == {
        i for i in range(10)
    }

    # covered!
    assert True

When run under pytest with assertion rewriting (the default), the multiline set comprehension is reported as partially covered, even though the comprehension on oneline is fully covered. I think this is a bug in coverage, not pytest's assertion rewriting, because this code passes:

import ast
from _pytest.assertion.rewrite import rewrite_asserts

oneline = """assert {i for i in range(10)} == {i for i in range(10)}"""
multiline = """assert {i for i in range(10)} == {
    i for i in range(10)
}"""

# Parse the expressions
oneline_tree = ast.parse(oneline)
multiline_tree = ast.parse(multiline)

# Dump the pre-assertion rewrite ASTs
multiline_dump_prerewrite = ast.dump(multiline_tree)
oneline_dump_prerewrite = ast.dump(oneline_tree)

# The ASTs should be the same
assert multiline_dump_prerewrite == oneline_dump_prerewrite

# Rewrite the asserts
rewrite_asserts(oneline_tree)
rewrite_asserts(multiline_tree)

# Dump the rewritten ASTs
oneline_dump_rewrite = ast.dump(oneline_tree)
multiline_dump_rewrite = ast.dump(multiline_tree)

# The ASTs should be the same
assert oneline_dump_rewrite == multiline_dump_rewrite

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingexoticUnusual execution environment

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions