pytest-dev / pytest-cov

Coverage plugin for pytest.
MIT License
1.72k stars 211 forks source link

ProcessPoolExecutor code does not get reported #578

Closed mikegrima closed 1 year ago

mikegrima commented 1 year ago

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.

mikegrima commented 1 year ago

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.

mikegrima commented 1 year ago

I'll also add that I did review this issue but the suggested fix didn't work for me: https://github.com/pytest-dev/pytest-cov/issues/165

ionelmc commented 1 year ago

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
mikegrima commented 1 year ago

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.