Skip to content

Branch coverage missing in async for loop w/ break (CPython 3.10.2) #1324

@vytas7

Description

@vytas7

Describe the bug
When an async for loop contains a conditional break (or return) from the loop, it manifests as missing branch coverage under CPython 3.10.2. The branch is correctly covered under CPython 3.8.x.

To Reproduce
How can we reproduce the problem? Please be specific. Don't link to a failing CI job. Answer the questions below:

  1. What version of Python are you using?
    CPython 3.10.2

  2. What version of coverage.py shows the problem? The output of coverage debug sys is helpful.
    coverage_version: 6.3.1

  3. What versions of what packages do you have installed? The output of pip freeze is helpful.
    Only coverage.

  4. What code shows the problem? Give us a specific commit of a specific repo that we can check out. If you've already worked around the problem, please provide a commit before that fix.
    Suppose there are two files in a directory, test.py and .coveragerc, respectively:

import asyncio


class CoverMe:
    def __init__(self, number):
        self._number = number

    async def _async_range(self):
        for n in range(self._number):
            yield n

    async def do_something(self):
        accumulated = 0
        async for n in self._async_range():
            accumulated += n
            if accumulated > 10:
                break

        return accumulated


async def main():
    print(await CoverMe(1).do_something())
    print(await CoverMe(3).do_something())
    print(await CoverMe(10).do_something())


if __name__ == '__main__':
    asyncio.run(main())
[run]
branch = True

[report]
show_missing = True

What commands did you run?
Inside the same directory with the two described files, run the following commands:

$ coverage erase
$ coverage run test.py
0
3
15
$ coverage report
Name      Stmts   Miss Branch BrPart  Cover   Missing
-----------------------------------------------------
test.py      20      0     10      2    93%   16->14, 28->exit
-----------------------------------------------------
TOTAL        20      0     10      2    93%

Expected behavior
Repeating the same steps on CPython 3.8.x yields:

Name      Stmts   Miss Branch BrPart  Cover   Missing
-----------------------------------------------------
test.py      20      0     10      1    97%   28->exit
-----------------------------------------------------
TOTAL        20      0     10      1    97%

... which illustrates that I didn't bother to try importing this module as opposed to running as the main script. But the branch is now covered as expected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcpythonReported as a bug in CPython

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions