3

When running unittests I would like to see deprecation warnings. It appears that since Python 2.7 deprecation warnings are silenced. I'll quote from the page:

For Python 2.7, a policy decision was made to silence warnings only of interest to developers by default. DeprecationWarning and its descendants are now ignored unless otherwise requested, preventing users from seeing warnings triggered by an application. This change was also made in the branch that became Python 3.2. (Discussed on stdlib-sig and carried out in issue 7319.)

Later it appears as though I should see deprecation warnings while running unittests:

The unittest module also automatically reenables deprecation warnings when running tests.

Well.. simply put, it doesn't work for me, so I must be doing something wrong. I've tested with the following code:

import warnings
import unittest

def spam():
    warnings.warn('test', DeprecationWarning, stacklevel=2)
    return 'spam'

class Eggs(object):
    def __init__(self):
        self.spam = spam()

class Test(unittest.TestCase):
    def test_warn(self):
        eggs = Eggs()
        self.assertEqual('spam', eggs.spam)

Then I run the code (saved in spam.py):

python -m 'unittest' spam

And this gives me the following output:

.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

No deprecation warning. So the question is; what am I doing wrong here?

4

2 回答 2

4

看起来文档是错误的 - 在 2.7 中 unittest 不会重新启用弃用警告。

>>> import warnings
>>> from pprint import pprint

>>> pprint(warnings.filters)
[('ignore', None, <type 'exceptions.DeprecationWarning'>, None, 0),
 ('ignore', None, <type 'exceptions.PendingDeprecationWarning'>, None, 0),
 ('ignore', None, <type 'exceptions.ImportWarning'>, None, 0),
 ('ignore', None, <type 'exceptions.BytesWarning'>, None, 0)]

>>> import unittest
>>> pprint(warnings.filters)
[('ignore', None, <type 'exceptions.DeprecationWarning'>, None, 0),
 ('ignore', None, <type 'exceptions.PendingDeprecationWarning'>, None, 0),
 ('ignore', None, <type 'exceptions.ImportWarning'>, None, 0),
 ('ignore', None, <type 'exceptions.BytesWarning'>, None, 0)]

...而且unittest.py我没有看到可以重新启用的内容DeprecationWarning

您当然可以自己启用它们:

warnings.simplefilter('always', DeprecationWarning)

或者在命令行上:

$ python -Wd -m 'unittest' spam
spam.py:10: DeprecationWarning: test
  self.spam = spam()
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK

或者将装饰器应用于您的每个unittest.TestCase功能,以便DeprecationWarning仅用于测试:

import warnings
import unittest

def enable_DeprecationWarning(fn):
    def _wrapped(*args, **kwargs):
        with warnings.catch_warnings():
            warnings.simplefilter('always', DeprecationWarning)
            return fn(*args, **kwargs)
    return _wrapped

def spam():
    warnings.warn('test', DeprecationWarning, stacklevel=2)
    return 'spam'

class Eggs(object):
    def __init__(self):
        self.spam = spam()

class Test(unittest.TestCase):
    @enable_DeprecationWarning
    def test_warn(self):
        eggs = Eggs()
        self.assertEqual('spam', eggs.spam)

if __name__ == '__main__':
        unittest.main()

命令行选项可能是单元测试的最佳选择,因为它不需要更改代码。

于 2014-08-26T15:16:52.803 回答
2

由于我使用 Eclipse 进行 Python 开发,因此我决定使用与建议不同的解决方案。也可以使用环境变量启用警告。如果环境变量PYTHONWARNINGS设置为default弃用,则会显示警告。

在 Eclipse (PyDev) 中,可以修改解释器以包含环境变量。这样,它仅适用于使用该解释器的项目。

pydev 解释器配置

于 2014-08-27T09:50:27.443 回答