pytest 固定装置从外部范围重新定义名称 [pylint]
Posted
技术标签:
【中文标题】pytest 固定装置从外部范围重新定义名称 [pylint]【英文标题】:pytest fixtures Redefining name from outer scope [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
。
如果我想将固定装置与函数保存在同一个文件中,最佳做法是什么?
-
在所有灯具前加上
_
?
禁用此pylint
检查测试?
更好的建议?
【问题讨论】:
【参考方案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】:它通常被禁用(1、2)。
有一个pylint-pytest 插件试图修复一些问题,但错误W0621
尚未修复。
【讨论】:
这个插件是否在pytest期间对pylint警告出错,而不是在测试代码中抑制pylint警告? 是的,插件 @insysion 链接到运行 pylint 作为 pytest 的一部分,与修复常见 pytest 夹具使用的 pylint 错误消息无关。 此插件在使用“启用”pytest 配置时似乎无法正常工作。任何“启用”的标志都优先于 pylint-pytest 尝试做的事情。以上是关于pytest 固定装置从外部范围重新定义名称 [pylint]的主要内容,如果未能解决你的问题,请参考以下文章