【问题标题】:pytest fixtures Redefining name from outer scope [pylint]pytest 固定装置从外部范围重新定义名称 [pylint]
【发布时间】:2018-02-15 18:52:36
【问题描述】:

我正在学习 pytest,并使用 pylint 对代码进行 lint。 但是pylint还是抱怨:
W0621: Redefining name %r from outer scope (line %s)

以下示例来自 pytest:

# test_wallet.py

@pytest.fixture
def my_wallet():
    '''Returns a Wallet instance with a zero balance'''
    return Wallet()

@pytest.mark.parametrize("earned,spent,expected", [
    (30, 10, 20),
    (20, 2, 18),
])
def test_transactions(my_wallet, earned, spent, expected):
    my_wallet.add_cash(earned)
    my_wallet.spend_cash(spent)
    assert my_wallet.balance == expected

从外部范围重新定义名称my_wallet

我找到了将_ 前缀添加到灯具名称的解决方法:_my_wallet

如果我想将固定装置与函数保存在同一个文件中,最佳做法是什么?

  1. 在所有灯具前加上_?
  2. 禁用此pylint 检查测试?
  3. 更好的建议?

【问题讨论】:

    标签: python pytest pylint fixture


    【解决方案1】:

    pytest docs@pytest.fixture 说这个:

    如果在定义它的同一模块中使用了一个fixture,则 夹具的函数名称将被函数 arg 遮蔽 请求夹具;解决此问题的一种方法是命名装饰 函数fixture_<fixturename> 然后使用 @pytest.fixture(name='<fixturename>').

    所以这个解决方案类似于你的选项 1,除了 pytest 作者建议为夹具函数提供一个更具描述性的名称。所以替换这两行

    @pytest.fixture
    def my_wallet():
    

    与:

    @pytest.fixture(name="my_wallet")
    def fixture_my_wallet():
    

    文档中的描述还暗示了另一种解决方案,即将固定装置移动到conftest.py,这样它们就与使用固定装置的测试代码不在同一个模块中。此位置对于在测试模块之间共享固定装置也很有用。

    【讨论】:

    • 这应该是有效的答案。
    • 这里是相关pytest docs的更新链接
    • 这行得通。但是如果你使用 mocker,你仍然会得到 pylint 错误。例如:from pytest_mock import mocker 后跟 def test_my_thing(mocker): 会给您一个 pylint 错误。我认为这就是为什么这么多人投票支持其他答案的原因,该答案建议对整个文件禁用此 pylint 规则。这很糟糕。在我看来,pylint 践踏了所有良好的 linting 规则。
    【解决方案2】:

    我刚刚在我的测试文件中禁用了该规则:

    # pylint: disable=redefined-outer-name
    # ^^^ this
    import pytest
    
    @pytest.fixture
    def my_wallet():
        '''Returns a Wallet instance with a zero balance'''
        return Wallet()
    
    @pytest.mark.parametrize("earned,spent,expected", [
        (30, 10, 20),
        (20, 2, 18),
    ])
    def test_transactions(my_wallet, earned, spent, expected):
        my_wallet.add_cash(earned)
        my_wallet.spend_cash(spent)
        assert my_wallet.balance == expected
    

    【讨论】:

    • 这很可悲。 lint 规则的存在是有充分理由的。我把这归咎于 pylint。
    【解决方案3】:

    在def中添加fixture的name参数和fixture_前缀。

    @pytest.fixture(name="my_wallet")
    def fixture_wallet():
        '''Returns a Wallet instance with a zero balance.'''
        return Wallet()
    
    @pytest.mark.parametrize("earned, spent, expected", [
        (30, 10, 20),
        (20, 2, 18),
    ])
    def test_transactions(my_wallet, earned, spent, expected):
        my_wallet.add_cash(earned)
        my_wallet.spend_cash(spent)
        assert my_wallet.balance == expected
    

    【讨论】:

      【解决方案4】:

      它通常被禁用(12)。

      有一个pylint-pytest 插件试图修复一些问题,但错误W0621 尚未修复。

      【讨论】:

      • 这个插件是否在pytest期间对pylint警告出错,而不是在测试代码中抑制pylint警告?
      • 是的,插件 @insysion 链接到运行 pylint 作为 pytest 的一部分,与修复常见 pytest 夹具使用的 pylint 错误消息无关。
      • 此插件在使用“启用”pytest 配置时似乎无法正常工作。任何“启用”的标志都优先于 pylint-pytest 尝试做的事情。
      猜你喜欢
      • 1970-01-01
      • 2020-02-22
      • 1970-01-01
      • 2018-02-10
      • 1970-01-01
      • 2018-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多