Skip to content

Duplicate file collection for non-pattern matching file #2679

Closed

Description

@elliterate

When py.test is executed with file_or_dir arguments for:

  1. a directory and
  2. a file that
    1. is in the directory but
    2. does not match the configured Python test module pattern (e.g., test_*.py),

the file will be collected twice.

I believe this is because the file in question is considered for collection twice (once as a member of an explicitly-requested directory and again as an explicitly-requested file) and matches Session#isinitpath both times, thus being collected twice.

This is similar to #1187, except that the file would not ordinarily be collected as a member of the directory, since it does not match the Python test module pattern. As such, this is not a case of explicitly requesting collection of the same file_or_dir twice.

Example

Setup

$ python --version
Python 2.7.13
$ pip list
pip (9.0.1)
py (1.4.34)
pytest (3.2.1)
setuptools (28.8.0)
$ tree
.
└── tests
    ├── _test_three.py
    ├── _test_two.py
    └── test_one.py

Scenario A: Default test collection

$ py.test --collect-only
===================================== test session starts =====================================
platform darwin -- Python 2.7.13, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: $HOME/src/pytest-duplicate-collection, inifile:
collected 1 item
<Module 'tests/test_one.py'>
  <Function 'test_one'>

================================ no tests ran in 0.01 seconds =================================

Scenario B: Explicit directory test collection

$ py.test --collect-only tests
===================================== test session starts =====================================
platform darwin -- Python 2.7.13, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: $HOME/src/pytest-duplicate-collection, inifile:
collected 1 item
<Module 'tests/test_one.py'>
  <Function 'test_one'>

================================ no tests ran in 0.01 seconds =================================

Scenario C: Explicit non-matching file test collection

$ py.test --collect-only tests/_test_two.py
===================================== test session starts =====================================
platform darwin -- Python 2.7.13, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: $HOME/src/pytest-duplicate-collection, inifile:
collected 1 item
<Module 'tests/_test_two.py'>
  <Function 'test_two'>

================================ no tests ran in 0.00 seconds =================================

Scenario D: Explicit directory and non-matching file test collection

$ py.test --collect-only tests tests/_test_two.py
===================================== test session starts =====================================
platform darwin -- Python 2.7.13, pytest-3.2.1, py-1.4.34, pluggy-0.4.0
rootdir: $HOME/src/pytest-duplicate-collection, inifile:
collected 3 items
<Module 'tests/_test_two.py'>
  <Function 'test_two'>
<Module 'tests/test_one.py'>
  <Function 'test_one'>
<Module 'tests/_test_two.py'>
  <Function 'test_two'>

================================ no tests ran in 0.01 seconds =================================

Activity

  1. nicoddemus commented on Aug 15, 2017

    @nicoddemus
    Member

    @elliterate thanks for the report and the well detailed reproducer, we appreciate it. 👍

  2. elliterate commented on Oct 6, 2017

    @elliterate
    ContributorAuthor

    This seems to be 'work as designed'.

    I don't understand how you reached that conclusion. Yes, this is what the code does, but that doesn't mean its behavior is by design. (If that were true, then there would be no such thing as a bug in software; everything would by definition be a feature, since that is how the code works.)

    In #1187, the argument was made that if py.test A causes test set {X} to be executed, it would be reasonable to infer that py.test A A would cause test set {X} + {X} to be executed. That is, if you request the collection of a path twice, it will collect all of the matching tests twice. I don't necessarily agree that it's a desirable behavior, but I can buy the argument that people might infer it.

    In this case, however, while py.test A causes test set {X} to be executed and py.test B causes test set {Y} to be executed, py.test A B causes test set {X + Y} + {Y} to be executed. In other words, the request to collect path B is altering the collection of path A. I see no reason for anyone to infer or desire this behavior and I believe that makes this a completely difference scenario from #1187.

  3. Zac-HD commented on Jul 21, 2026

    @Zac-HD
    Member

    Closing as resolved: fixed by #13704 (closing #12083), which made overlapping collection arguments resolve to their common prefix. Verified with this issue's reproducer on current main: pytest --collect-only tests tests/_test_two.py collects 1 item, with no duplication and no pattern-bypassing collection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: collectionrelated to the collection phasetype: bugproblem that needs to be addressed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions