So using file addresses (aka generated subtargets)...
# development
h
So using file addresses (aka generated subtargets) always runs into some issues with the file
conftest.py
. We end up generating a
python_tests()
target for the
conftest.py
file, then try running
./pants test conftest.py
, which causes Pytest to fail because there are no tests inside. This is an issue with
conftest.py
, but also any util file in a
python_tests()
target. Some possible solutions: 1. Stop having
conftest.py
belong to
python_tests()
and have it belong to
python_library()
.
python_tests()
should only have files with actual tests in them. This is conceptually pure, but also not very ergonomic, especially if your tests live in their own folders and you only had
python_tests()
targets before. 2. Special case
pytest_runner.py
to no-op if the file name is
conftest.py
. But this would not catch if you had other util files in your
python_tests()
target, and perhaps you could actually have a test in your
conftest.py
? 3. Change
pytest_runner.py
to not fail if the tests were empty. I argue that this failure is a feature, though - it’s caught issues for me in the past. And Pants should generally emulate Pytest as much as possible.
cc @happy-kitchen-89482 @witty-crayon-22786. @aloof-angle-91616 you may be interested too
My feeling is that #1 is the correct thing to do. The metadata from
python_tests()
doesn’t make sense for a conventional
conftest.py
without any tests in it. What does
timeout=120
mean for that type of file? The key intuition is that now “targets are metadata for some files”, rather than “targets are a collection of files plus some metadata”
👍 1
I think the convention we would recommend in your BUILD file for a folder with only tests is:
Copy code
python_tests()

python_library(name="conftest")
That’s not too horrible imo. Not great if you are a 1.x user upgrading to 2.x tho
👍 1
w
yea, i agree on #1. it’s already the case that any non-test code in the directory requires the lib
ie, if you have any test helper code, it isn’t matched by the default glob.
✍️ 1
a
reading through this i would be much more comfortable with #1 as it seems like the correct thing to do and we can possibly figure out a nicer syntax for it later
👍 1
@hundreds-father-404 could you describe the issue when upgrading from 1.x to 2.x? i would have thought your example BUILD file would be already valid and working for 1.x
+1 to your point about
timeout=120
as well
💯 1
w
yea, i think that the example BUILD file is valid and working. it’s just that folks might not have done that in all cases
h
it’s just that folks might not have done that in all cases
Yeah, this is precisely the issue. If your tests lived in their own dedicated folder, it’s common to only put this in your BUILD file:
Copy code
python_tests(
  dependences=[...]
)
Now you have to go manually update every BUILD file to do this:
Copy code
python_tests(
   dependencies=[':conftest', ...]
)

python_library(name="conftest")
Although, actually, if you have
--python-infer-conftests
on (the default), you would solely need to add the
python_library(name="conftest")
target 🙂 You woulnd’t need to update the
dependencies
of your
python_tests
target because we’ll infer it. So, still not great, but not as horrible as before
Hey @polite-garden-50641, does
tests.py
in Django usually have actual tests in it? It’s not only util code, right?
a
i would definitely want to have an explicit target covering the conftest file in any case. this could also be a job for reviving https://github.com/pantsbuild/pants/pull/9434 for BUILD file introspection (if we wanted to automate adding this)
p
I am not aware of any convention regarding tests.py file in django projects...
👍 1
h
Okay no worries. Per https://docs.djangoproject.com/en/3.1/topics/testing/overview/#writing-tests, the info block “Where should the tests live?“, it looks like tests do live there. Only wanted to verify with you, but I think that’s what it’s for.
e
The issue here is both that conftest.py is a util file (does not have tests) and is named *test.py - right? You need both things to hit the error.
👍 1
h
We went out of our way to include
conftest.py
in the default globs for
python_tests()
. If we remove that explicit entry, then it no longer will belong by default to a
python_tests
target
👍 1
Because the new globs are `[test.py, test.py, tests.py]`; the underscore means
conftest.py
doesn’t match
👍 1
a
that kind of makes sense. i’m not sure that someone reading a repo is necessarily going to have the intuition that one is a test with an underscore and the other not, but i’m not trying to reopen that discussion
e
I still don't really follow all this but it seems to make sense if possible to respect how pytest works, which is to infer sibling or ancestor conftests.py files as test dependencies.
👍 1
IE: dependency inference for pytest needs to go beyond import scraping.
a
i’ll read up on that so i can understand this
h
which is to infer sibling or ancestor conftests.py files as test dependencies.
Ah, there have been some changes to do exactly that in the past month, thanks to
--python-infer-conftests
option
👍 1
Ditto on
__init__.py
, via
--python-infer-inits
. (Although that inference is a little more complex - it took a few iterations for us to get it right. tl;dr is that if no target owns the file, we will still include it in the chroot as an undeclared dependency)
e
Ok, then I really don't understand this thread at all. Carry on!
Aha you added --python-infer-conftests and you just incorrectly had that code create a python_tests target instead of a library that you stitched in as a dep to the sibling or descendant tests of it. I think I understand now. This is all just about correcting that error via the #1 fix.
h
Sort of.
--python-infer-conftests
would generate a subtarget from whatever the owner was. It doesn’t care if it’s a
python_library
vs. a
python_tests
target; it will generate the new target from whatever the original was The real issue is the enormous model change in https://github.com/pantsbuild/pants/pull/10511. Now, we run tests one-file-at-a-time, over every file belonging to the
python_tests
target. Because
python_tests
defaults to
conftest.py
being in its default globs, it was common for that to be included in the target.
Where
--python-infer-contests
is really relevant is that it makes the solution less painful than it would have otherwise been. As described in https://github.com/pantsbuild/pants/pull/10603, most users won’t need to touch their
dependencies
fields due to this change - inference will do the right thing
j
How does this impact non-python resources, like json blobs, used for tests? Would these still be defined as resources and added as a dependency for a
python_test
target type?
h