pytest-asyncio icon indicating copy to clipboard operation
pytest-asyncio copied to clipboard

iter_markers_with_node() has double entries for async test functions

Open jvtm opened this issue 10 months ago • 4 comments

Description

With pytest-asyncio and async def test_...() function decorated with @pytest.mark.xyz each marker appears twice in request.node.iter_markers_with_node().

Environment

pip list

Package        Version
-------------- -------
iniconfig      2.0.0
packaging      24.0
pip            23.3.1
pluggy         1.4.0
pytest         8.1.1
pytest-asyncio 0.23.6

pytest.ini

[pytest]
log_level = INFO
markers = 
    network: Requires live network
    slow: Slow to execute
    smoke: Smoke tests
asyncio_mode = auto

OS / Python

  • cPython 3.12.2
  • Linux / amd64

Test

test_iter_markers.py

import logging

import pytest

logger = logging.getLogger("markerdebug")


def check_markers(request: pytest.FixtureRequest) -> None:
    markers = []
    marker_ids = set()
    for node, marker in request.node.iter_markers_with_node():
        logging.info(
            "node_id=%r node=%r marker_id=%r marker=%r",
            id(node),
            node,
            id(marker),
            marker,
        )
        markers.append(marker)
        marker_ids.add(id(marker))
    assert len(markers) == len(marker_ids)


@pytest.mark.slow
@pytest.mark.network
@pytest.mark.usefixtures("monkeypatch")
async def test_debug_iter_markers_async(request: pytest.FixtureRequest) -> None:
   check_markers(request) 


@pytest.mark.slow
@pytest.mark.network
@pytest.mark.usefixtures("monkeypatch")
def test_debug_iter_markers_sync(request: pytest.FixtureRequest) -> None:
    check_markers(request)

Output

============================================= test session starts =============================================
platform linux -- Python 3.12.2, pytest-8.1.1, pluggy-1.4.0
configfile: pytest.ini
plugins: asyncio-0.23.6
asyncio: mode=Mode.AUTO
collected 2 items                                                                                             

test_iter_markers.py F.                                                                                 [100%]

================================================== FAILURES ===================================================
________________________________________ test_debug_iter_markers_async ________________________________________

request = <FixtureRequest for <Coroutine test_debug_iter_markers_async>>

    @pytest.mark.slow
    @pytest.mark.network
    @pytest.mark.usefixtures("monkeypatch")
    async def test_debug_iter_markers_async(request: pytest.FixtureRequest) -> None:
>      check_markers(request)

test_iter_markers.py:28: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

...
>       assert len(markers) == len(marker_ids)
E       AssertionError: assert 7 == 4
E        +  where 7 = len([Mark(name='usefixtures', args=('monkeypatch',), kwargs={}), Mark(name='network', args=(), kwargs={}), Mark(name='slow...rgs=('monkeypatch',), kwargs={}), Mark(name='network', args=(), kwargs={}), Mark(name='slow', args=(), kwargs={}), ...])
E        +  and   4 = len({140114061819008, 140114061990688, 140114070935392, 140114075899504})

test_iter_markers.py:21: AssertionError
---------------------------------------------- Captured log call ----------------------------------------------
INFO     root:test_iter_markers.py:12 node_id=140114061847456 node=<Coroutine test_debug_iter_markers_async> marker_id=140114061990688 marker=Mark(name='usefixtures', args=('monkeypatch',), kwargs={})
INFO     root:test_iter_markers.py:12 node_id=140114061847456 node=<Coroutine test_debug_iter_markers_async> marker_id=140114070935392 marker=Mark(name='network', args=(), kwargs={})
INFO     root:test_iter_markers.py:12 node_id=140114061847456 node=<Coroutine test_debug_iter_markers_async> marker_id=140114061819008 marker=Mark(name='slow', args=(), kwargs={})
INFO     root:test_iter_markers.py:12 node_id=140114061847456 node=<Coroutine test_debug_iter_markers_async> marker_id=140114061990688 marker=Mark(name='usefixtures', args=('monkeypatch',), kwargs={})
INFO     root:test_iter_markers.py:12 node_id=140114061847456 node=<Coroutine test_debug_iter_markers_async> marker_id=140114070935392 marker=Mark(name='network', args=(), kwargs={})
INFO     root:test_iter_markers.py:12 node_id=140114061847456 node=<Coroutine test_debug_iter_markers_async> marker_id=140114061819008 marker=Mark(name='slow', args=(), kwargs={})
INFO     root:test_iter_markers.py:12 node_id=140114061847456 node=<Coroutine test_debug_iter_markers_async> marker_id=140114075899504 marker=Mark(name='asyncio', args=(), kwargs={})
=========================================== short test summary info ===========================================
FAILED test_iter_markers.py::test_debug_iter_markers_async - AssertionError: assert 7 == 4
========================================= 1 failed, 1 passed in 0.02s =========================================
(Pdb) pprint.pprint(markers)
[Mark(name='usefixtures', args=('monkeypatch',), kwargs={}),
 Mark(name='network', args=(), kwargs={}),
 Mark(name='slow', args=(), kwargs={}),
 Mark(name='usefixtures', args=('monkeypatch',), kwargs={}),
 Mark(name='network', args=(), kwargs={}),
 Mark(name='slow', args=(), kwargs={}),
 Mark(name='asyncio', args=(), kwargs={})]

jvtm avatar Apr 13 '24 18:04 jvtm

(Pdb) pprint.pprint(request.node.own_markers)
[Mark(name='usefixtures', args=('monkeypatch',), kwargs={}),
 Mark(name='network', args=(), kwargs={}),
 Mark(name='slow', args=(), kwargs={}),
 Mark(name='usefixtures', args=('monkeypatch',), kwargs={}),
 Mark(name='network', args=(), kwargs={}),
 Mark(name='slow', args=(), kwargs={}),
 Mark(name='asyncio', args=(), kwargs={})]

jvtm avatar Apr 13 '24 18:04 jvtm

seems like this is a bug in pytest-asyncio

RonnyPfannschmidt avatar Apr 14 '24 12:04 RonnyPfannschmidt

https://github.com/pytest-dev/pytest-asyncio/blob/dfe6e7c94aad7fc6cccae3f35705c39b26183bfa/pytest_asyncio/plugin.py#L405 incorrectly adds the values

RonnyPfannschmidt avatar Apr 14 '24 12:04 RonnyPfannschmidt

@jvtm Could you try https://github.com/pytest-dev/pytest-asyncio/pull/838 and report if it solves your issue?

seifertm avatar Jul 04 '24 08:07 seifertm

@jvtm The linked PR seems to fix the issue with your code example

seifertm avatar Jul 08 '24 12:07 seifertm