Skip to content

Does not re-initialize "consumables" in other decorators #160

Description

@NickGoog

Hi, I saw something related in the docs:

when using an iterator or a generator, all the items will be loaded into memory before the start of the test run

https://github.com/wolever/parameterized#exhaustive-usage-examples

Not sure if this deserves a separate mention or a warning in code. Sorry if this is a known issue, and I couldn't find it.

The Problem: “Consumables” (e.g. iterators) declared in non-parameterized decorators that are used by one test case remain consumed for other test cases.

Reproduction:

from parameterized import parameterized
from unittest import mock, TestCase

class MyIterator:
  def get_iterator(self):
    raise NotImplementedError

class TestConsumableInOtherDecorator(TestCase):
  @parameterized.expand(
     [('first run',), ('second run',)]
  )
  @mock.patch.object(MyIterator, 'get_iterator', new=mock.Mock(return_value=iter([1])))
  def test_the_problem(self, case):
    print(case)
    assert list(MyIterator.get_iterator()) == [1]

  @parameterized.expand(
     [('first run',), ('second run',)]
  )
  @mock.patch.object(MyIterator, 'get_iterator', new=mock.Mock(return_value=[1]))
  def test_isolating_the_problem(self, case):
    print(case)
    assert list(MyIterator.get_iterator()) == [1]

  @parameterized.expand(
     [('first run',), ('second run',)]
  )
  @mock.patch.object(MyIterator, 'get_iterator')
  def test_the_workaround(self, case, mock_get_iterator):
    mock_get_iterator.return_value = iter([1])
    print(case)
    assert list(MyIterator.get_iterator()) == [1]


Output:

$ python -m unittest -v test.py
test_isolating_the_problem_0_first_run (test.TestConsumableInOtherDecorator) ... first run
ok
test_isolating_the_problem_1_second_run (test.TestConsumableInOtherDecorator) ... second run
ok
test_the_problem_0_first_run (test.TestConsumableInOtherDecorator) ... first run
ok
test_the_problem_1_second_run (test.TestConsumableInOtherDecorator) ... second run
FAIL
test_the_workaround_0_first_run (test.TestConsumableInOtherDecorator) ... first run
ok
test_the_workaround_1_second_run (test.TestConsumableInOtherDecorator) ... second run
ok

======================================================================
FAIL: test_the_problem_1_second_run (test.TestConsumableInOtherDecorator)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/google/home/hartunian/Desktop/lib/python3.10/site-packages/parameterized/parameterized.py", line 533, in standalone_func
    return func(*(a + p.args), **p.kwargs)
  File "/usr/lib/python3.10/unittest/mock.py", line 1379, in patched
    return func(*newargs, **newkeywargs)
  File "/usr/local/google/home/hartunian/Desktop/lib/python3.10/site-packages/parameterized/parameterized.py", line 81, in dummy_func
    return orgfunc(*args, **kwargs)
  File "/usr/lib/python3.10/unittest/mock.py", line 1379, in patched
    return func(*newargs, **newkeywargs)
  File "/usr/local/google/home/hartunian/Desktop/test.py", line 17, in test_the_problem
    assert list(MyIterator.get_iterator()) == [1]
AssertionError

We're fine with the workaround but just wanted to raise awareness.

Thanks!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions