Skip to content

Integrate pytest warnings #2072

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

Merged

Conversation

nicoddemus
Copy link
Member

This PR starts the work to integrate fschulze/pytest-warnings.

I managed to preserve history and authorship, and the integration itself was smooth.

It is working as can be seen here:

============================= test session starts =============================
platform win32 -- Python 3.5.0, pytest-3.1.0.dev0, py-1.4.31, pluggy-0.4.0
rootdir: C:\pytest, inifile: tox.ini
plugins: hypothesis-3.5.0
collected 10 items

test_warnings.py ..........

=========================== pytest-warning summary ============================
WW0 in .tmp\test_warnings.py:7 the following warning was recorded:
 test_warnings.py:11: PendingDeprecationWarning: Pending
  warnings.warn(PendingDeprecationWarning('Pending'))

WW0 in .tmp\test_warnings.py:7 the following warning was recorded:
 test_warnings.py:14: DeprecationWarning: DeprecationWarning
  warnings.warn(DeprecationWarning('DeprecationWarning'))

================ 10 passed, 2 pytest-warnings in 0.02 seconds =================

Some points I would like to discuss before moving this further:

  1. I think we should rename pytest-warnings back to just warnings, since it now it displays system warnings as well as pytest's own warnings.
  2. The output is 3 lines per warning, I kind like that other summaries occupies only one line per summary.
  3. Minor: test_warnings.py:14: should include the name of the function as well IMHO (test_warnings.py:test_foo:14:).
  4. Surprisingly, pytest's own test suite is generating tons of warnings, you can see the full list here. I think we should fix those and then enable the -W error switch so future warnings break immediately.
  5. The large number of warnings generated in such a relatively small project makes me wonder if we should leave the option to "ignore" by default. It will probably scare users the first time they execute 3.1.0 because I'm sure it will spew a ton of warnings. Then users can enable this gradatively and select which warnings they want to handle.
  6. A small issue, but when we execute tests using testdir which raise warnings, the warnings are also displayed in the "main" session. I made a quick experiment to fix this by deleting the warnings after they were printed by the terminal reporter, but that didn't work. I will have to investigate more.

Would love to hear your feedback.

fschulze and others added 13 commits June 22, 2016 12:21
This is useful when to use regular expressions, like for example ignore
a bunch of dynamic messages
    --filterwarnigns 'ignore:Please use assert.* instead.:'

Or ignore all the warnings in a sub-backage
    --filterwarnigns 'ignore:::package.submodule.*'

This is also available in the ini file as the filterwarnigns options
Add a warning option which does not escape its arguments.
@nicoddemus nicoddemus changed the base branch from master to features November 21, 2016 10:54
@nicoddemus
Copy link
Member Author

  1. I see we only capture warnings around pytest_runtest_call. I think we should also capture for setup and teardown as well.

@nicoddemus
Copy link
Member Author

  1. Also we might want to include a mechanism where the user opts to only see warnings from their own projects?

@nicoddemus
Copy link
Member Author

Btw there are failing tests because now there are more "pytest-warnings" being displayed, for various reasons. Would like to nail down the discussion before fixing those.

@nicoddemus
Copy link
Member Author

Gentle pinging @fschulze, @RonnyPfannschmidt, @hpk42, @The-Compiler and @flub

Would like to get the discussion going. 😁

@fschulze
Copy link
Contributor

fschulze commented Dec 9, 2016

No one does anything about stuff if it's ignored, so I would vote against ignoring by default. It's better to add info how to hide warnings. Especially selectively like for modules you don't care about or specific types of warnings. A pointer to docs when there are more then 5 warnings perhaps.

  • The error code can go (discussed during the sprint).
  • Including the function name would indeed be nice.
  • Maybe we could use output that can be c'n'p into the -W option? Haven't thought that through.
  • I'm not sure we can do a one line output. We print which test caused the warning and we print where the warning originated in the code base. Both are very useful.

I agree that we should capture setup/teardown as well.

The original plan was to also replace the calls to .warn in the pytest code base with the python warning system. Not sure if that is feasible or not.

Currently warnings aren't transferred when using xdist, that's a major blocker IMO and I've got no clue what is involved to fix that.

@nicoddemus
Copy link
Member Author

Thanks @fschulze, I will evolve the implementation a bit based on your feedback!

@nicoddemus
Copy link
Member Author

FIxed the issue with testdir by using warnings.catch_warnings instead of WarningsRecorder during the hook call.

WarningsRecorder calls the original warnings.showwarnings function, which in its original form
only writes the formatted warning to sys.stdout, while warnings.catch_warnings doesn't.

Calling the original warnings.showwarnings has the effect that nested WarningsRecorder all catch the warnings:

with WarningsRecorder() as rec1:
    with WarningsRecorder() as rec2:
        warnings.warn(UserWarning, 'some warning')

(both rec1 and rec2 sees the warning)

When running tests with testdir, the main pytest session would then see the warnings created by
the internal code being tested (if any), and the main pytest session would end up with warnings as well.

I'm considering removing WarningsRecorder in favor of catch_warnings, but will do so in a separate PR.

This has the benefical side-effect of not calling the original
warnings.showwarnings function, which in its original form
only writes the formatted warning to sys.stdout.

Calling the original warnings.showwarnings has the effect that nested WarningsRecorder all catch the warnings:

with WarningsRecorder() as rec1:
    with WarningsRecorder() as rec2:
        warnings.warn(UserWarning, 'some warning')

(both rec1 and rec2 sees the warning)

When running tests with `testdir`, the main pytest session would then see the warnings created by
the internal code being tested (if any), and the main pytest session would end up with warnings as well.
The rationale of using node ids is that users can copy/paste it to run a chosen test
@nicoddemus nicoddemus changed the title Integrate pytest warnings [WIP] Integrate pytest warnings Mar 21, 2017
@nicoddemus
Copy link
Member Author

I think this is now ready for review! 😅

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.08%) to 92.585% when pulling 916d272 on nicoddemus:integrate-pytest-warnings into de8607d on pytest-dev:features.

@The-Compiler
Copy link
Member

The CI seems to disagree 😉

# produced by path.local
ignore:bad escape.*:DeprecationWarning:re
# produced by path.readlines
ignore:.*U.*mode is deprecated:DeprecationWarning
Copy link
Member

Choose a reason for hiding this comment

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

Those should probably be fixed in pylib

Copy link
Member

Choose a reason for hiding this comment

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

pytest-dev/py#116 is there to fix this

- pytester was creating a 'pexpect' directory to serve as temporary dir, but due to the fact that
   xdist adds the current directory to sys.path, that directory was being considered as candidate
   for import as a package. The directory is empty and a warning was being raised about
   it missing __init__ file, which is now turned into an error by our filterwarnings config
   in pytest.ini.

- Decided to play it safe and ignore any warnings during `pytest.importorskip`.

- pytest-xdist and execnet raise two warnings which should be fixed upstream:
   pytest-dev/pytest-xdist/issues/133
For some reason pypy raises this warning in the line that the catch_warnings block was added:

______________________________ ERROR collecting  ______________________________
C:\ProgramData\chocolatey\lib\python.pypy\tools\pypy2-v5.4.1-win32\lib-python\2.7\pkgutil.py:476: in find_loader
    loader = importer.find_module(fullname)
c:\pytest\.tox\pypy\site-packages\_pytest\assertion\rewrite.py:75: in find_module
    fd, fn, desc = imp.find_module(lastname, path)
<builtin>/?:3: in anonymous
    ???
E   ImportWarning: Not importing directory 'c:\users\bruno\appdata\local\temp\pytest-of-Bruno\pytest-3192\testdir\test_cmdline_python_package0' missing __init__.py
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.07%) to 92.587% when pulling 74b54ac on nicoddemus:integrate-pytest-warnings into de8607d on pytest-dev:features.

@nicoddemus
Copy link
Member Author

nicoddemus commented Mar 22, 2017

Summary of the problems that lead to CI failing in some environments:

  • pytester was creating a pexpect directory to serve as temporary dir, but due to the fact that
    xdist adds the current directory to sys.path, that directory was being considered as candidate
    for import as a package. The directory is empty and a warning was being raised about
    it missing __init__ file, which is now turned into an error by our filterwarnings config
    in pytest.ini.
    Because of this problem, decided to play it safe and ignore any warnings during pytest.importorskip.

  • pytest-xdist and execnet raise two warnings which should be fixed upstream: Warnings generated by pytest-xdist pytest-xdist#133

  • For some reason pypy raises an ImportWarning in one of the tests, but not in CPython. Decided to ignore that warning in that particular test.

Turning warnings into errors is fun. 😎

@@ -1008,7 +1008,7 @@ def spawn_pytest(self, string, expect_timeout=10.0):
The pexpect child is returned.

"""
basetemp = self.tmpdir.mkdir("pexpect")
basetemp = self.tmpdir.mkdir("temp-pexpect")
Copy link
Member

Choose a reason for hiding this comment

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

that must have been so puzzleing

@RonnyPfannschmidt
Copy link
Member

looks good to me, unless someone notices something i missed, i'll merge this afternoon,

great dob 👍

@RonnyPfannschmidt
Copy link
Member

@nicoddemus that bit again ^^ , thanks, i'll merge after its green

@nicoddemus
Copy link
Member Author

Heh just noticed it this morning, but was busy so only now managed to get to it. 😁

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.07%) to 92.587% when pulling 0c1c258 on nicoddemus:integrate-pytest-warnings into de8607d on pytest-dev:features.

@RonnyPfannschmidt RonnyPfannschmidt merged commit 2a130da into pytest-dev:features Mar 22, 2017
@QuLogic
Copy link

QuLogic commented Mar 23, 2017

Will this work correctly with xdist? cf. fschulze/pytest-warnings#3 and pytest-dev/pytest-xdist#92.

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.

8 participants