【发布时间】:2021-07-23 00:49:20
【问题描述】:
关于 pytest、str() 和 python 错误类型之间的交互的一些事情会破坏完整的错误测试,我们想要确认错误返回的 EXACT TEXT。
下面的例子:
def erroring_func(name, required_item_list):
# skip boring bit. Just throw an error.
raise KeyError(f'{name} is missing required item(s): {required_item_list')
def test_erroring_func()
with pytest.raises(KeyError) as err:
name = 'This dataframe'
required_item_list = ['a column']
_ = erroring_func(name, required_item_list)
assert str(err.value) == f"{name} is missing required item(s): {required_item_list}"
这看起来很合理,但会返回错误:
assert '"This dataframe is missing required item(s): [\'lat\']"' == "This dataframe is missing required item(s): ['lat']
不知何故,str(err.value) 在输出中创建了单个反斜杠,很难在 f 字符串 (actually impossible) 中重新创建或在创建后插入到字符串中。
【问题讨论】:
-
所以,问题是
KeyError有一个自定义__str__并且KeyError的构造函数是缺失的键,这就是你看到它被引用的原因。反斜杠实际上并不存在,它只是字符串的表示以单引号开头,因此嵌入的单引号将在代码中以这种方式显示。KeyError也可能是错误的异常类型 -
断言中的字符串不匹配,因此为
KeyError定义的__str__方法肯定改变了一些东西。我很想相信实际的错误日志是反斜杠,但它可能是别的东西?至于为什么 KeyError,这是一个自定义检查,用于在昂贵的计算之前确认 df 列,从而提出后来成为关键错误的内容(并使错误消息真正有用)。可以创建一个自定义错误类,但我很想了解为什么默认类在 pytest 中表现不佳。 -
更改您的断言以使用
'"message"',就像 KeyError 所做的那样——注意引用是 both 类型的引号(您传入的字符串的代表)。比较str(KeyError("foo'bar"))和str(ValueError("foo'bar")),你会更好地看到KeyError的__str__在做什么 -
我还强烈建议在测试中使用逻辑——它会掩盖你的问题并使你感到困惑:testing.googleblog.com/2014/07/…
-
感谢您的帮助!需要在适当类型和顺序的引号中双重换行文本字符串 (yuck)。 Google thinkpiece 很有趣,谢谢。总的来说,我不同意这种想法,因为这种想法使单元测试很难维护,尽管我可以看到规格变化较慢的大型组织可能会这样想(即,如果您不更改单元测试,谁会关心可维护性)。根据对此的回复:andrewtrumper.com/2014/08/complex-logic-in-unit-tests.html
标签: python-3.x pytest f-string