pytest-dev/pytest-cov

ProcessPoolExecutor code does not get reported

mikegrima opened this issue · 4 comments

Summary

Hello. I am making use of a ProcessPoolExecutor context manager and all code that runs within it is not deemed as covered. I am running this on macOS.

I execute this in tox normally, but this has the same issue outside of tox as well.

The command I run is: pytest --cov --cov-report term-missing tests -n auto. The behavior is the same with or without -n auto for pytest-xdist.

Expected vs actual result

Expected to have the code covered. The actual result is that the code it not seen as covered.

Reproducer

Here is essentially the code that I have:

main.py:

import asyncio
import multiprocessing
from concurrent.futures import ProcessPoolExecutor

async def my_tasker(loop, *args, **kwargs):
    ctx = multiprocessing.get_context("fork")  # my code needs this for a variety of reasons
    with ProcessPoolExecutor(max_workers=10, mp_context=ctx) as executor:
        tasks = []
        for x in range(0, 100):
            tasks.append(loop.run_in_executor(executor, run_in_process, *args, **kwargs))

        results = await asyncio.gather(*tasks)

    return results

def run_in_process(*args, **kwargs):
    # These lines are not seen as covered:
    asdf = 1 + 2
    qwer = 3 + 4
    return "completed"

def main():
    some_args = ["1", "2", "3"]
    loop = asyncio.new_event_loop()
    results = loop.run_until_complete(my_tasker(loop, *some_args))
    loop.close()

    print(results)

    return results

if __name__ == "__main__":
    main()

test_main.py:

from main import main

def test_stuff():
    assert main()

Run pytest --cov --cov-report term-missing -n auto for my tests.

This is the output:

======================================================================================= test session starts ========================================================================================
platform darwin -- Python 3.10.3, pytest-7.2.1, pluggy-1.0.0
rootdir: mycode
plugins: xdist-3.1.0, cov-4.0.0
gw0 [1] / gw1 [1] / gw2 [1] / gw3 [1] / gw4 [1] / gw5 [1] / gw6 [1] / gw7 [1] / gw8 [1] / gw9 [1]
.                                                                                                                                                                                            [100%]

---------- coverage: platform darwin, python 3.10.3-final-0 ----------
Name           Stmts   Miss  Cover   Missing
--------------------------------------------
main.py           24      4    83%   18-20, 33
test_main.py       3      0   100%
--------------------------------------------
TOTAL             27      4    85%

======================================================================================== 1 passed in 0.79s =========================================================================================

Per the output, lines 18-20 are missing, but they are in fact executed.

Versions

Python 3.10.3
pytest==7.2.1
pytest-cov==4.0.0
pytest-xdist==3.1.0

I should hopefully have the code OSS'd soon so that could provide more context, but in the meantime, the code above demonstrates the issue.

I did an additional test without the context being set to fork, and it does successfully report the code as covered. It fails when the process is set to fork.

I'll also add that I did review this issue but the suggested fix didn't work for me: #165

Yes but that is irrelevant now since multiprocessing support was removed in pytest-cov 4.0. You can try adding this in your coveragerc for the support bultin support from coverage:

[run]
concurrency = multiprocessing
parallel = true
sigterm = true

Thanks @ionelmc ! Those changes worked for me. I struggled to find these details though. I mostly reviewed the documentation on this page: https://pytest-cov.readthedocs.io/en/latest/subprocess-support.html. I would be happy to make a PR to add the above details.