python - unittest 从迭代器收到 None 而不是引发的错误
问题描述
我仍在学习 unittest,因此无法判断下面 test_iterators.py 中的测试用例中是否缺少某些内容。有人可以帮我理解为什么在单元测试中未能提出 ValueError 吗?以下是脚本:
迭代器.py
"""
Simple class to count from zero to N
"""
class count_to(object):
def __init__(self, nber):
self.nber = nber
def __iter__(self):
return count_to_iter(self.nber)
class count_to_iter(object):
def __init__(self, nber):
self.stopat = nber
self.current_nber = 0
def __next__(self):
if self.stopat < 0:
raise ValueError
elif self.current_nber > self.stopat:
raise StopIteration
self.current_nber += 1
return self.current_nber - 1
if __name__ == '__main__':
for x in count_to(-1):
print(x)
测试/test_iterators.py
import unittest
import iterators
class TestBaseIterators(unittest.TestCase):
def setUp(self):
pass
# Can't get the negative test right yet. It returns None instead of raising a ValueError
# Calling iterators.py directly and execute main successfully raised a ValueError however
def test_negative(self):
with self.assertRaises(ValueError): iterators.count_to(-1)
if __name__ == '__main__':
unittest.main()
我之前使用过类似的方法来测试引发的错误并且它有效。但是,对于这个特定的测试用例,这是我从测试中得到的。
test_negative (test_iterators.TestBaseIterators) ... FAIL
NoneType: None
======================================================================
FAIL: test_negative (test_iterators.TestBaseIterators)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/kerwei/Git/Concepts/tests/test_iterators.py", line 19, in test_negative
with self.assertRaises(ValueError): iterators.count_to(-1)
AssertionError: ValueError not raised
----------------------------------------------------------------------
Ran 1 test in 0.004s
FAILED (failures=1)
如果我直接从 调用迭代器__main__
,我可以成功接收ValueError。
(py36) Kers-MacBook-Air:Concepts kerwei$ python iterators.py
Traceback (most recent call last):
File "iterators.py", line 29, in <module>
for x in count_to(-1):
File "iterators.py", line 19, in __next__
raise ValueError
ValueError
解决方案
count_to(-1)
创建一个新count_to
实例,它不会对其进行迭代,但是您将测试放在self.stop_at
value 上并ValueError
在方法中引发 ,因此在迭代实例count_to_iter.__next__
之前显然不会得到 ValueError 。count_to
天真的解决方法是强制迭代,即:
def test_negative(self):
with self.assertRaises(ValueError):
# passing the iterable to `list` will force iteration
list(iterators.count_to(-1))
但根本问题实际上更多是设计问题:此时引发 ValueError 远非最佳,因为它只会在实际使用可迭代时发生,因此您必须检查调用堆栈,直到找到count_to
传递的位置一个错误的值。一个更好的解决方案是检查该值并最终直接在count_to
实例化点处引发,因此它总是立即中断(而不是“最终,当您尝试在代码的某些可能远程部分使用迭代器时):
class count_to(object):
def __init__(self, nber):
if nber < 0:
raise ValueError("count_to argument must be a positive integer")
self.nber = nber
def __iter__(self):
return count_to_iter(self.nber)
然后您当前的测试代码将按预期工作。
推荐阅读
- qt - QAudioOutput 的最大实例数?
- apple-id - 有没有办法找到 Apple ID 的令牌?
- android - 使用 react-native-maps 组件打开屏幕时 Expo 独立应用程序崩溃
- php - 如何在woocommerce商店的主页上获取产品ID?
- android - 关闭时的软键盘强制片段更改
- python - TypeError:读取json时字符串索引必须是整数
- regex - Dart Regex:只允许点和数字
- c# - 在网格上生成随机孔的算法
- python - 如何编辑 Python 路径 - 我想我在安装 Visual Studio 后不小心更改了它
- spring-boot - 如何在我的项目中强制提交消息?