将(逐步)`DeprecationWarnings` 转变为 Python 中的致命错误

Turn (progressively) `DeprecationWarnings` into fatal errors in Python

我们的测试套件有很多 DeprecationWarnings 来自我们自己的代码。我的团队一直在不修复(或检查警告)受影响的测试的情况下弃用某些东西。我认为解决此问题的最佳方法是在测试上下文中 运行 时将这些警告转换为异常或测试失败。这样,团队不会在不重新调整受影响的测试的情况下引入 DeprecationWarnings。

更重要的是,如果这种转换可以是渐进的(我们有很多测试需要开始一项一项地修复),那就太好了。我可以不时减少的某种白名单

这是当前情况:

import warnings

class Addition:
    def __init__(self, int1, int2):
        self.int1 = int1
        self.int2 = int2

    def get_result(self):
        warnings.warn("The method get_result() is being deprecated. Use result() instead.",
                      DeprecationWarning, 2)
        return self.result()

    def result(self):
        return self.int1 + self.int2
from unittest import TestCase
from addition import Addition

class CustomTestCase(TestCase):
    # ...
    pass

class TestResultOperations(CustomTestCase):
    def test_addition(self):
        addition = Addition(2, 3)
        self.assertEqual(addition.get_result(), 5)

如果有帮助,我们正在 运行 这些毒物测试。

没有完整的答案,但有一些提示:

我不知道如何逐步做到这一点。

我通常不会将所有警告都变成异常,因为第 3 方库中的警告也会导致测试失败。

不过,您可以在 tox 的命令部分为测试命令添加前缀。然后,带有非零 return 代码的命令也可以 运行 并显示错误,而不会使完整的 tox 运行 失败。

我很确定您可以使用 https://docs.python.org/3/using/cmdline.html#envvar-PYTHONWARNINGS 将警告变成错误,但我必须查一下。我目前在移动。

更新

正如您提到的,您使用 pytest 作为测试 运行ner...

[testenv:businessasusual]
commands = pytest <your-tests>  # works as usual

[testenv:deprecations]
commands = - pytest -W error::DeprecationWarning <your-tests>  # works

...其中

  • 前导破折号(包括 space!!)使得 tox 运行 作为一个整体不会失败,但仍然会显示失败!!
  • "-W error::DeprecationWarning" 把警告变成错误

那么您可以始终 运行 两者,或者仅通过 -e 中的一个。

这最终意味着,显示了现在的测试错误,但不要破坏 tox 运行。

这是我最终的做法:

class CustomTestCase(TestCase):
    @classmethod
    def setUpClass(cls):
      allow_DeprecationWarning_modules = [ 
            "...",  # This is the allowlist, from where I will 
            "...",  # progressively start removing modules that
            "...",  # use deprecated calls
      ]  
      warnings.filterwarnings("error", category=DeprecationWarning)
      for mod in allow_DeprecationWarning_modules:
          warnings.filterwarnings("default", category=DeprecationWarning, module=mod)

方法 setUpClass 在开始测试之前运行一次。在那里,我将操作 "error" 设置为 DeprecationWarning 警告类别,并附加“例外”以作为 "default" 运行。请注意,这是与测试运行器无关的。