Skip to content

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

@NickGoog

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!

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