AckslD / nvim-pytrize.lua

Easily navigate pytest parametrize entries and fixtures with neovim
26 stars 1 forks source link

JumpToFixture chooses wrong fixture definition #8

Open dapc11 opened 1 year ago

dapc11 commented 1 year ago

Hello,

If you have a Python project, with multiple test files (e.g. test_x.py and test_y.py).

Both of these test files declares the following fixture:

@pytest.fixture
def config_dir(tmp_path):
    return tmp_path

Both test files have tests using it's local config_dir fixture. But if one invokes PytrizeJumpFixture in test_y.py, it would jump to the declaration in test_x.py instead of the one in test_y.py.

Any ideas?

AckslD commented 1 year ago

What does pytest --fixtures -v show?

dapc11 commented 1 year ago
pytest --fixtures -v
============================================================================ test session starts ============================================================================
platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 -- /usr/bin/python3
cachedir: .pytest_cache
metadata: {'Python': '3.8.10', 'Platform': 'Linux-5.15.0-83-generic-x86_64-with-glibc2.29', 'Packages': {'pytest': '6.2.5', 'py': '1.11.0', 'pluggy': '1.0.0'}, 'Plugins': {'xdist': '2.3.0', 'forked': '1.4.0', 'dependency': '0.5.1', 'cov': '3.0.0', 'html': '2.1.1', 'metadata': '2.0.2'}}
rootdir: /home/dapc11/repos/python_test
plugins: xdist-2.3.0, forked-1.4.0, dependency-0.5.1, cov-3.0.0, html-2.1.1, metadata-2.0.2
collected 203 items / 1 error / 202 selected
cache -- ../../.local/lib/python3.8/site-packages/_pytest/cacheprovider.py:505
    Return a cache object that can persist state between testing sessions.

    cache.get(key, default)
    cache.set(key, value)

    Keys must be ``/`` separated strings, where the first part is usually the
    name of your plugin or application to avoid clashes with other cache users.

    Values can be any object handled by the json stdlib module.

capsys -- ../../.local/lib/python3.8/site-packages/_pytest/capture.py:903
    Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.

    Thi captured output is made available via ``capsys.readouterr()`` method
    calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``text`` objects.

capsysbinary -- ../../.local/lib/python3.8/site-packages/_pytest/capture.py:920
    Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.

    The captured output is made available via ``capsysbinary.readouterr()``
    method calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``bytes`` objects.

capfd -- ../../.local/lib/python3.8/site-packages/_pytest/capture.py:937
    Enable text capturing of writes to file descriptors ``1`` and ``2``.

    The captured output is made available via ``capfd.readouterr()`` method
    calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``text`` objects.

capfdbinary -- ../../.local/lib/python3.8/site-packages/_pytest/capture.py:954
    Enable bytes capturing of writes to file descriptors ``1`` and ``2``.

    The captured output is made available via ``capfd.readouterr()`` method
    calls, which return a ``(out, err)`` namedtuple.
    ``out`` and ``err`` will be ``byte`` objects.

doctest_namespace [session scope] -- ../../.local/lib/python3.8/site-packages/_pytest/doctest.py:721
    Fixture that returns a :py:class:`dict` that will be injected into the
    namespace of doctests.

pytestconfig [session scope] -- ../../.local/lib/python3.8/site-packages/_pytest/fixtures.py:1365
    Session-scoped fixture that returns the :class:`_pytest.config.Config` object.

    Example::

        def test_foo(pytestconfig):
            if pytestconfig.getoption("verbose") > 0:
                ...

record_property -- ../../.local/lib/python3.8/site-packages/_pytest/junitxml.py:282
    Add extra properties to the calling test.

    User properties become part of the test report and are available to the
    configured reporters, like JUnit XML.

    The fixture is callable with ``name, value``. The value is automatically
    XML-encoded.

    Example::

        def test_function(record_property):
            record_property("example_key", 1)

record_xml_attribute -- ../../.local/lib/python3.8/site-packages/_pytest/junitxml.py:305
    Add extra xml attributes to the tag for the calling test.

    The fixture is callable with ``name, value``. The value is
    automatically XML-encoded.

record_testsuite_property [session scope] -- ../../.local/lib/python3.8/site-packages/_pytest/junitxml.py:343
    Record a new ``<property>`` tag as child of the root ``<testsuite>``.

    This is suitable to writing global information regarding the entire test
    suite, and is compatible with ``xunit2`` JUnit family.

    This is a ``session``-scoped fixture which is called with ``(name, value)``. Example:

    .. code-block:: python

        def test_foo(record_testsuite_property):
            record_testsuite_property("ARCH", "PPC")
            record_testsuite_property("STORAGE_TYPE", "CEPH")

    ``name`` must be a string, ``value`` will be converted to a string and properly xml-escaped.

    .. warning::

        Currently this fixture **does not work** with the
        `pytest-xdist <https://github.com/pytest-dev/pytest-xdist>`__ plugin. See issue
        `#7767 <https://github.com/pytest-dev/pytest/issues/7767>`__ for details.

caplog -- ../../.local/lib/python3.8/site-packages/_pytest/logging.py:476
    Access and control log capturing.

    Captured logs are available through the following properties/methods::

    * caplog.messages        -> list of format-interpolated log messages
    * caplog.text            -> string containing formatted log output
    * caplog.records         -> list of logging.LogRecord instances
    * caplog.record_tuples   -> list of (logger_name, level, message) tuples
    * caplog.clear()         -> clear captured records and formatted log output string

monkeypatch -- ../../.local/lib/python3.8/site-packages/_pytest/monkeypatch.py:30
    A convenient fixture for monkey-patching.

    The fixture provides these methods to modify objects, dictionaries or
    os.environ::

        monkeypatch.setattr(obj, name, value, raising=True)
        monkeypatch.delattr(obj, name, raising=True)
        monkeypatch.setitem(mapping, name, value)
        monkeypatch.delitem(obj, name, raising=True)
        monkeypatch.setenv(name, value, prepend=False)
        monkeypatch.delenv(name, raising=True)
        monkeypatch.syspath_prepend(path)
        monkeypatch.chdir(path)

    All modifications will be undone after the requesting test function or
    fixture has finished. The ``raising`` parameter determines if a KeyError
    or AttributeError will be raised if the set/deletion operation has no target.

recwarn -- ../../.local/lib/python3.8/site-packages/_pytest/recwarn.py:28
    Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.

    See http://docs.python.org/library/warnings.html for information
    on warning categories.

tmpdir_factory [session scope] -- ../../.local/lib/python3.8/site-packages/_pytest/tmpdir.py:201
    Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.

tmp_path_factory [session scope] -- ../../.local/lib/python3.8/site-packages/_pytest/tmpdir.py:208
    Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.

tmpdir -- ../../.local/lib/python3.8/site-packages/_pytest/tmpdir.py:223
    Return a temporary directory path object which is unique to each test
    function invocation, created as a sub directory of the base temporary
    directory.

    By default, a new base temporary directory is created each test session,
    and old bases are removed after 3 sessions, to aid in debugging. If
    ``--basetemp`` is used then it is cleared each session. See :ref:`base
    temporary directory`.

    The returned object is a `py.path.local`_ path object.

    .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html

tmp_path -- ../../.local/lib/python3.8/site-packages/_pytest/tmpdir.py:241
    Return a temporary directory path object which is unique to each test
    function invocation, created as a sub directory of the base temporary
    directory.

    By default, a new base temporary directory is created each test session,
    and old bases are removed after 3 sessions, to aid in debugging. If
    ``--basetemp`` is used then it is cleared each session. See :ref:`base
    temporary directory`.

    The returned object is a :class:`pathlib.Path` object.

------------------------------------------------------------------ fixtures defined from pytest_cov.plugin ------------------------------------------------------------------
no_cover -- ../../.local/lib/python3.8/site-packages/pytest_cov/plugin.py:386
    A pytest fixture to disable coverage.

cov -- ../../.local/lib/python3.8/site-packages/pytest_cov/plugin.py:392
    A pytest fixture to provide access to the underlying coverage object.

----------------------------------------------------------------- fixtures defined from pytest_html.plugin ------------------------------------------------------------------
extra -- ../../.local/lib/python3.8/site-packages/pytest_html/plugin.py:104
    Add details to the HTML reports.

    .. code-block:: python

        import pytest_html
        def test_foo(extra):
            extra.append(pytest_html.extras.url('http://www.example.com/'))

--------------------------------------------------------------- fixtures defined from pytest_metadata.plugin ----------------------------------------------------------------
metadata [session scope] -- ../../.local/lib/python3.8/site-packages/pytest_metadata/plugin.py:43
    Provide test session metadata

include_metadata_in_junit_xml [session scope] -- ../../.local/lib/python3.8/site-packages/pytest_metadata/plugin.py:49
    Provide test session metadata

-------------------------------------------------------------------- fixtures defined from xdist.plugin ---------------------------------------------------------------------
worker_id [session scope] -- ../../.local/lib/python3.8/site-packages/xdist/plugin.py:270
    Return the id of the current worker ('gw0', 'gw1', etc) or 'master'
    if running on the master node.

testrun_uid [session scope] -- ../../.local/lib/python3.8/site-packages/xdist/plugin.py:279
    Return the unique id of the current test.

-------------------------------------------------------- fixtures defined from test.test_y --------------------------------------------------------

config_dir -- python/test/test_y.py:19
    python/test/test_y.py:19: no docstring available

unittest_setUpClass_fixture_ImageTest [class scope] -- ../../.local/lib/python3.8/site-packages/_pytest/unittest.py:145
    /home/dapc11/.local/lib/python3.8/site-packages/_pytest/unittest.py:145: no docstring available

unittest_setUpClass_fixture_ImportTest [class scope] -- ../../.local/lib/python3.8/site-packages/_pytest/unittest.py:145
    /home/dapc11/.local/lib/python3.8/site-packages/_pytest/unittest.py:145: no docstring available

unittest_setUpClass_fixture_VolumeTest [class scope] -- ../../.local/lib/python3.8/site-packages/_pytest/unittest.py:145
    /home/dapc11/.local/lib/python3.8/site-packages/_pytest/unittest.py:145: no docstring available

------------------------------------------------------ fixtures defined from test.test_x ------------------------------------------------------
config_dir -- python/test/test_x.py:15
    python/test/test_x.py:15: no docstring available

unittest_setUpClass_fixture_PropertyTest [class scope] -- ../../.local/lib/python3.8/site-packages/_pytest/unittest.py:145
    /home/dapc11/.local/lib/python3.8/site-packages/_pytest/unittest.py:145: no docstring available

So I guess pytrize is taking this output and then taking the last occurrence of given fixture. Is that correct? Perhaps there should be a bit more logic to it, to take the current buffer into consideration.

AckslD commented 1 year ago

Indeed, hmm, not fully sure how the logic should be in general. I guess it should look for fixtures in the current file, then iteratively upwards in conftest.py's and then from plugins? What do you think?

dapc11 commented 1 year ago

I think that order you suggested sounds good and accurate.