-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Node.get_marker needs a proper replacement #3446
Comments
well consider yourself lucky, pytest-retunfailures is basically broken based on the code you posted, so its lucky we can fix it now, welcome to #568 - markers stain on things in addition the example you posted is likely incorrect as well, as its absolutely unclear which mark from which level should take priority in the code you posted a mark on the class/module level would always be prioritized over a function scope one (and users most likely want it the other way around) |
the main reason there is no marks_by name is, that it would also be incomplete and half-wrong - the api was iterate on in the marks pr and thrown out for lack of clarity in details |
Note that that example was from @nicoddemus - which reinforces my point pretty well, this is difficult to get right. This is exactly why pytest should solve this problem and not everyone using it. |
@The-Compiler the main problem is that we have no clear idea on how to solve this right either |
@The-Compiler is absolutely right that we should nail down the documentation before releasing 3.6 (this is one of the points I made during the review). I'm confused:
The "closest" mark is not what we want in this case? |
Guys, gentle ping. This is blocking the 3.6 release so we need to reach a consensus soon. |
i propose a require_name argument to iter_markers, allowing to filter by name i can implement this evening or tommorow |
We can't update
(Little bickshedding: I think calling the parameter just If we add this new parameter to fake_os = request.node.get_marker('fake_os')
if not fake_os:
return
name = fake_os.args[0] What if instead we add a new |
I agree that a |
On Mon 07 May 2018 at 11:37 +0000, Bruno Oliveira wrote:
Guys, gentle ping. This is blocking the 3.6 release so we need to reach a consensus soon.
I'd be somewhat careful not to try and do this too hurriedly. It's bad
to break things for users. And really bad if we break things for
indirect users (a user of a plugin really doesn't care, they just want
their tests to keep running).
|
Thanks for the thorough feedback Florian!
On Thu 03 May 2018 at 22:38 -0700, Florian Bruhin wrote:
Continuing the discussion from #3317 (especially #3317 (comment)) here - cc @nicoddemus @RonnyPfannschmidt @flub
# Current situation
I'm trying the 3.6.0 release (#3445), here's what I see with `-Wall`:
## `pytest-rerunfailures` breaks
```python
INTERNALERROR> Traceback (most recent call last):
INTERNALERROR> [...]
INTERNALERROR> File ".../lib/python3.6/site-packages/pytest_rerunfailures.py", line 123, in pytest_runtest_protocol
INTERNALERROR> reruns = get_reruns_count(item)
INTERNALERROR> File ".../lib/python3.6/site-packages/pytest_rerunfailures.py", line 80, in get_reruns_count
INTERNALERROR> if "reruns" in rerun_marker.kwargs:
INTERNALERROR> File ".../lib/python3.6/site-packages/_pytest/mark/structures.py", line 20, in warned
INTERNALERROR> warnings.warn(warning, stacklevel=2)
INTERNALERROR> _pytest.deprecated.RemovedInPytest4Warning: MarkInfo objects are deprecated as they contain the merged marks.
INTERNALERROR> Please use node.iter_markers to iterate over markers correctly
```
We crash plugins because we want to emit a warning? Is this the
intention? This seems not great to me.
With that kind of ugly construct, I can guarantee you: People will
make mistakes (or plugins will handle it differently) and you'll end
up with *more* issues regarding marker handling than before. Suddenly,
only *some* markers will smear, others will have other funny issues
(what if I forget the `else:` for the `for`), and so on.
You're right. We should aim for a direct replacement for get_marker.
We want the default case to be that only the closest marker applies,
right? So get an equivalent API which does that, and document that's
the replacement for the "default case" where you don't need to worry
about those issues at all.
+1
|
Only for testsuites using |
On Mon 07 May 2018 at 11:50 +0000, Bruno Oliveira wrote:
We can't update `Node.get_marker` to return the closest marker because currently it returns the "merged" markers for backward compatibility, correct?
> i propose a require_name argument to iter_markers, allowing to filter by name
(Little bickshedding: I think calling the parameter just `name` is sufficient)
If we add this new parameter to `iter_markers`, how the example below should change to use the new API?
```python
fake_os = request.node.get_marker('fake_os')
if not fake_os:
return
name = fake_os.args[0]
```
What if instead we add a new `get_closest_marker(name)` function,
which returns the closest marker to the node with the given name, or
`None` if not found? This would provide a more direct replacement of
current `get_marker(name)` usages.
What would happen if we just deprecate having multiple markers of the
same name which end up on one node at all? Because everything that's
being discussed here so far does not address the part of the feeback
that no two plugins will ever handle this situation in the same way. It
rightfully is the task of the API pytest provides to do this.
If we do that then maybe even keeping .get_marker() is a sane option?
How different are the new MarkInfo objects?
|
IIUC that's what was done,
I think @RonnyPfannschmidt knows that from the top of his head and can answer more easily. 😁 |
Oh definitely. Sorry if it came across that way, I just meant to point out that this is a release blocker so we can't postpone it indefinitely. But you are right to emphasize that we should strive for a good solution, and not just hush for something to get the release out. 👍 |
@flub we cant deprecate having multiple marks with the same name, it would break skip, skip_if and xfail_usages that happen in practice i consider the perception that one "typically" wants the closes mark a false one - for example at a work project - i believe actually all custom marks (about a dozen ones for different purposes) have requirements for correctly working with individual markings, considering them in order |
I see. Just to share, I reviewed all custom marks we use at work and they all actually are meant to work as the "closest" one. I think the same can be said about all the markers @The-Compiler brought up in his original post, so I guess the mileage varies according to the codebase. I propose then:
What do you guys think? |
So maybe it helps enumerating the strategies for handling marks. I'm doing this partially to expose my naivety about this again, but also because if we're finding this so hard then maybe we should spell these various things out very clearly in the documentation complete with sensible examples of how these marking strategies work. Anyway, here my attempt:
So I think this really should be added to the documentation of marks and then can be referred too in the news for the release as well as justification. Also this maybe also suggests what the APIs should be like: get_closes_mark() which returns a single mark and a get_all_marks() which returns a set. What do you all think? Am I completely off the mark or is this useful? |
@flub thanks, enumerating all cases is very helpful. In my mind there were only two use cases, 1) and 2). I also can't think of examples for 3) and 4). |
|
Please tell me that pun was intentional. 😆 I agree there are probably those cases. Some thoughts about each: Case 1 and 3 are basically the same, just ordered vs. unordered, right? I think the current Case 2 is what I think is the most common case - I'm not just speaking for qutebrowser here, I've seen many pytest testsuites and plugins by now. We should support it in some straightforward way, and I agree a Case 4 might be useful, but I'm not sure - @RonnyPfannschmidt do you have a more concrete example? Maybe it's useful when I just never want any marker ambiguity in my testsuite (because this can be hard to reason about)? I'm not sure how the API would look, though. I first thought about a |
whops, the one about 4 was a typo - i meant 3, sorry for the confusion |
@The-Compiler what would i propose 2 steps a) updating |
@RonnyPfannschmidt that sounds great to me. 👍 |
my initial implementation has some bugs, will reiterate |
almost complete |
I think this can now be closed right? |
Continuing the discussion from #3317 (especially #3317 (comment)) here - cc @nicoddemus @RonnyPfannschmidt @flub
Current situation
I'm trying the 3.6.0 release (#3445), here's what I see with
-Wall
:pytest-rerunfailures
breakspytest-qt
breakslocal things in my testsuite break
Problems
Insufficient documentation
So, the deprecation warning tells me to use
node.iter_markers
. Looking at the docs, all I can see is "iterate over all markers of the node" and forget_marker(name)
a "warning: deprecated" (with wrong ReST-syntax, too).If I'm not aware of the problem of marker smearing (and I wasn't really, I've never done strange subclassing stuff in tests), I'm quite lost there. If it wasn't for @nicoddemus' example I would be pretty lost here, and write something based on guesswork.
Bad abstraction
The suggested alternative to
Is supposedly:
With that kind of ugly construct, I can guarantee you: People will make mistakes (or plugins will handle it differently) and you'll end up with more issues regarding marker handling than before. Suddenly, only some markers will smear, others will have other funny issues (what if I forget the
else:
for thefor
), and so on.We want the default case to be that only the closest marker applies, right? So get an equivalent API which does that, and document that's the replacement for the "default case" where you don't need to worry about those issues at all.
Conclusion
I feel like this should block a 3.6.0 release. If we release something with deprecation warnings, no replacement, and bad documentation, then plugins and testsuites which want to preserve backwards compatibility will end up with three ways of getting a marker, each probably different in another subtle way.
The text was updated successfully, but these errors were encountered: