[TIP] assertRaisesRegex with exceptions from inside a generator

Andrew Dalke dalke at dalkescientific.com
Sun Jan 8 12:16:32 PST 2017


On Jan 8, 2017, at 5:15 PM, Andrew Dalke <dalke at dalkescientific.com> wrote:
> (This is an unusual approach.

I realized I can make a much easier example which shows the problem.

##### code under test
def simple_gen():
    yield 1, None
    try:
        1/0
    except ZeroDivisionError as err:
        yield None, err
    yield 3, None

class Spam:
    def __init__(self):
        self.gen = simple_gen()
    def get_next(self):
        value, err = next(self.gen)
        if err is not None:
            raise err
        return value
#####


The following test prints "simple test passed", as expected. It shows that the generator can be continued:

##### simple test case (does not use unittest)
def simple_test():
    spam = Spam()
    assert spam.get_next() == 1
    try:
        spam.get_next()
    except ZeroDivisionError:
        pass
    else:
        raise AssertionError
    assert spam.get_next() == 3
    print("simple test passed")

simple_test()
#####

The corresponding unittest code, while simpler:

##### test using unittest
import unittest

class TestGen(unittest.TestCase):
    def test_gen(self):
        spam = Spam()
        self.assertEqual(spam.get_next(), 1)
        with self.assertRaises(ZeroDivisionError):
            spam.get_next()
        self.assertEqual(spam.get_next(), 3)

unittest.main()
#####

fails with:

##### output from the unittest test case:
======================================================================
ERROR: test_gen (__main__.TestGen)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "clear.py", line 40, in test_gen
    self.assertEqual(spam.get_next(), 3)
  File "clear.py", line 13, in get_next
    value, err = next(self.gen)
StopIteration

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (errors=1)
#####

This is the same behavior which I earlier showed was a consequence of calling traceback.clear_frames(), which was implemented in http://bugs.python.org/issue17934 and
added to unittest as a consequence of http://bugs.python.org/issue9815#msg217443 . It was not designed for my use case.

I'll report this to python-bugs.

Cheers,

				Andrew
				dalke at dalkescientific.com





More information about the testing-in-python mailing list