C_Z_
C_Z_

Reputation: 7796

Testing classwide attributes

Let's say I have a module named foo with a class Bar. Bar has a classwide counter attribute that allows me to track the order which instances were created. foo looks like this:

from itertools import count

class Bar:
    class_count = count(0)
    def __init__(self):
        self.id = self.class_count.next()

Now I have a test file where I am testing the various functionalities of Bar. I am unsure of how to test this id attribute, because the other unittests are creating instances of Bar and so I don't know what the given id of a Bar instance should be. Furthermore, this behavior of my class means that my unittests are independent of each other, which is undesirable. How should I structure my unittests so the tests are independent of each other?

Upvotes: 1

Views: 268

Answers (2)

Dan
Dan

Reputation: 1884

I would stub out Bar to bypass the constructor.

class BarStub(Bar):
  def __init__(self):
    self.class_count = None
    self.id = None

Now you can test like this:

class TestBar(...):
  def setUp(...)
    ...
    self.bar = BarStub()

  def test_foo_should_blah_when_blah(self):
    with mock.patch.object(self.bar, 'count_class', side_effect=[...]) as mock_count:
      actual = self.bar.unit_under_test(...)
      mock_count.assert_called_with([...])

Upvotes: 0

MSeifert
MSeifert

Reputation: 152657

You could use setUp to safe the current count and then temporarily reset the count. Then with tearDown you restore the original state again:

from itertools import count
import unittest

class Bar:
    class_count = count(0)
    def __init__(self):
        self.id = next(self.class_count)


class TestBar(unittest.TestCase):
    def setUp(self):
        self.nxtcount = next(Bar.class_count)  # safe current state
        Bar.class_count = count(0)             # reset to 0

    def tearDown(self):
        Bar.class_count = count(self.nxtcount) # reset to old state

    def teststh1(self):
        x = Bar()
        self.assertEqual(x.id, 0)

    def teststh2(self):
        x1 = Bar()
        x2 = Bar()
        x3 = Bar()
        self.assertEqual(x1.id, 0)
        self.assertEqual(x2.id, 1)
        self.assertEqual(x3.id, 2)

This makes sure every test method will start with a Bar.class_count of 0.

Upvotes: 1

Related Questions