单元测试未从迭代器收到任何信息,而是引发了错误

时间:2019-06-03 08:40:55

标签: python python-3.x unit-testing

我仍在学习单元测试,因此无法在下面的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

1 个答案:

答案 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

然后您当前的测试代码将按预期工作。