我仍在学习单元测试,因此无法在下面的test_iterators.py中判断我的测试用例是否缺少某些内容。有人可以帮我理解为什么在单元测试中无法引发ValueError吗?以下是脚本:
iterators.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)
tests / 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
答案 0 :(得分:0)
count_to(-1)
创建一个新的count_to
实例,它不会对其进行迭代,但是您将测试置于self.stop_at
的值上,并在{{1 }}方法,因此,显然,您需要在ValueError
实例上进行迭代,否则不会收到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))
的位置上直接升高,以使其始终立即中断(而不是“最终,当您尝试在迭代器的某个可能较远的部分中使用迭代器时)代码):
count_to
然后您当前的测试代码将按预期工作。