Skip to content

terminal: fix progress report with duplicate nodeids #6599

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

Closed
wants to merge 13 commits into from

Conversation

blueyed
Copy link
Contributor

@blueyed blueyed commented Jan 28, 2020

Fixes #6597.

TODO:

@blueyed blueyed force-pushed the fix-progress-same-nodeids branch from b059834 to cc26d81 Compare January 28, 2020 15:26
@blueyed blueyed changed the title terminal: fix progress report with duplicate nodeids [WIP] terminal: fix progress report with duplicate nodeids Jan 30, 2020
@blueyed blueyed changed the title [WIP] terminal: fix progress report with duplicate nodeids [blocked] terminal: fix progress report with duplicate nodeids Jan 30, 2020
@blueyed blueyed force-pushed the fix-progress-same-nodeids branch from cc26d81 to aac97ef Compare February 9, 2020 09:07
@blueyed blueyed changed the title [blocked] terminal: fix progress report with duplicate nodeids terminal: fix progress report with duplicate nodeids Feb 9, 2020
@blueyed blueyed changed the title terminal: fix progress report with duplicate nodeids [WIP] terminal: fix progress report with duplicate nodeids Feb 9, 2020
What's needed to fix pytest-dev#3088
seems to be checking for `rep.when == "setup"`.

This then needs adjustments though (to code done in
pytest-dev#3110) to make this work with
xdist.

It appears to make sense to split it into hooks that are run per test
(for eventually writing if past edge), and one that gets run at the end
really (not requiring to check for "last item" then).
@blueyed blueyed changed the title [WIP] terminal: fix progress report with duplicate nodeids [WIP/blocked] terminal: fix progress report with duplicate nodeids Feb 10, 2020
TODO:

- `test_xdist_verbose` fails: first two tests are reporting at 10%
  already.

Conflicts:
	changelog/6597.bugfix.rst
	src/_pytest/terminal.py
	testing/test_terminal.py
@blueyed blueyed changed the title [WIP/blocked] terminal: fix progress report with duplicate nodeids [WIP/] terminal: fix progress report with duplicate nodeids Feb 18, 2020
@blueyed blueyed changed the title [WIP/] terminal: fix progress report with duplicate nodeids [WIP] terminal: fix progress report with duplicate nodeids Feb 18, 2020
@blueyed blueyed changed the title [WIP] terminal: fix progress report with duplicate nodeids terminal: fix progress report with duplicate nodeids Feb 19, 2020
@blueyed
Copy link
Contributor Author

blueyed commented Feb 19, 2020

be6a7cd changes a lot, but is actually a bit of a revert, see the commit message.
I think it's better to just have a count, and not to use a set() as a "workaround", and consider this to be ready - assuming tests pass.

@bluetech
Copy link
Member

According to this comment by @nicoddemus, duplicate nodeids are no longer possible. The change (set -> counter) might still make sense, but maybe the test doesn't?

@blueyed
Copy link
Contributor Author

blueyed commented Feb 28, 2020

@bluetech nothing prevents you from creating duplicate nodeids. The test here uses a private property, but you could also yield Items with duplicate nodeids.

The test is for a corner case, yes, but makes sense.

It's also unfortunate that the patch is so big, but only because it was not done properly/better before and it has to undo previous changes (IIRC).

@bluetech
Copy link
Member

Some lazy questions that would help me understand the diff -- feel free to dismiss.

Considering each change I can detect separately:

  1. Changing when progress is indicated from if verbosity > 0 to if rep.when == "call" or (rep.when == "setup" and rep.failed). I understand why you removed it from the verbosity check - incrementing a counter doesn't cost anything so no need for it. But what are these new conditions?

  2. Changing from set -> counter. This seems to make sense regardless, why use a heavy data structure when it's not needed? But the question is why was a set used in the first place? What it because it was assumed that no duplicate IDs are possible, or because it explicitly wanted to handle duplicate IDs by deduplicating them?

  3. Changing from pytest_runtest_logfinish to pytest_runtest_teardown. IIUC these two should be mostly equivalent for this use case -- is it not so? If not, why? I possible I think this change should be avoided, mostly because the "log" hooks seem to exist particularly for this use case (reporting), and the code already uses logstart and logreport and it seems nice to use the matching logfinish hook.

  4. Change from checking _is_last_item in pytest_runtest_logfinish hook to unconditionally running in pytest_runtestloop hookwrapper. This seems nice, but I'm not sure it's worth it as long as _is_last_item still exists. If you can get rid of _is_last_item entirely in favor the hook, that would be a nice cleanup.

@@ -440,6 +440,8 @@ def pytest_runtest_logreport(self, report: TestReport) -> None:
else:
markup = None
self._add_stats(category, [rep])
if rep.when == "call" or (rep.when == "setup" and rep.failed):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this come after if not letter and not word:? Because "probably passed setup/teardown" should not be reported again.

progress_length = len(" [{}/{}]".format(str(num_tests), str(num_tests)))
else:
progress_length = len(" [100%]")
def pytest_runtest_teardown(self) -> None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious, why using pytest_runtest_teardown instead of pytest_runtest_logfinish? On pytest-xdist I think pytest_runtest_teardown is called only on worker nodes (because they actually run the tests), not on master (which only does reporting). The pytest_runtest_log* run on both master and workers, by design.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm strange, I commented out this function from your branch, and I still get the exact same output both with xdist/without, and -v and normal modes.


With the patch as is:

λ pytest testing\test_nodes.py
======================== test session starts ========================
collected 11 items

testing\test_nodes.py ...........                              [100%]

======================== 11 passed in 0.10s =========================

Commenting out pytest_runtest_teardown:

 λ pytest testing\test_nodes.py
======================== test session starts ========================
collected 11 items

testing\test_nodes.py ...........                              [100%]

======================== 11 passed in 0.10s =========================

With the patch as is:

λ pytest testing\test_nodes.py -n2
======================== test session starts ========================
gw0 [11] / gw1 [11]
...........                                                    [100%]
======================== 11 passed in 0.93s =========================

Commenting out pytest_runtest_teardown:

λ pytest testing\test_nodes.py -n2
======================== test session starts ========================
gw0 [11] / gw1 [11]
...........                                                    [100%]
======================== 11 passed in 0.92s =========================

So I guess pytest_runtest_teardown is not being used?

I got curious, and when in master and pytest_runtest_logfinish commented out, the [%] progress indicator is not printed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pytest_runtest_log* run on both master and workers, by design.

That might result in too much being reported then (if both master and nodes report the same item(s)).
Changed it to use pytest_runtest_logfinish again, let's see if it passes.

"""Write final progress indicator."""
yield
if (
getattr(self, "_tests_ran", False)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should avoid attributes being set but not declared on __init__ when that is possible; this has been a great source of confusion/bugs in the past.

@nicoddemus
Copy link
Member

But the question is why was a set used in the first place? What it because it was assumed that no duplicate IDs are possible, or because it explicitly wanted to handle duplicate IDs by deduplicating them?

IIRC the former, because it is easier/more solid to just use the node ids if they are unique. But indeed, there's nothing preventing plugins to create items with duplicated ids, so using a set here is not really the right call.

blueyed added a commit to blueyed/pytest that referenced this pull request Mar 14, 2020
blueyed added a commit to blueyed/pytest that referenced this pull request Mar 14, 2020
@blueyed
Copy link
Contributor Author

blueyed commented Mar 27, 2020

@nicoddemus @bluetech
Please squash-merge or close it.

@blueyed
Copy link
Contributor Author

blueyed commented Mar 31, 2020

(btw: nodeids were generated automatically not too long ago, which is actually something I've came up with somewhere already: 5e59357)

@nicoddemus nicoddemus closed this May 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Progression is wrong when using empty string in parametrized tests
3 participants