2

Unit testing newbie here. I have an abstract base class with one concrete, public method and one abstract, private method. Several child classes implement this private method:

@add_metaclass(ABCMeta)
class Base(object):

    def concrete(self, x, y):
        x = self._abstract(x)
        return x, y

    @abstractmethod
    def _abstract(self, x):
        pass


class Child(Base):

    def _abstract(self, x):
        return x + 1

What is the best way to unit test the methods in these classes? In my initial attempt I created a MockBase and a set of tests in BaseTests common to all children of the original base class (BaseTests skips tests to avoid redundancy on execution). Child tests inherit from BaseTests.

class MockBase(Base):

    def _abstract(self, x):
        return x


class BaseTests(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        if cls is BaseTests:
            raise unittest.SkipTest("Skipping BaseTests.")
        super(BaseTests, cls).setUpClass()

    def setUp(self):
        super(BaseTests, self).setUp()
        self.class_ = MockBase()

    def test_concrete_returns_y(self):
        _, y = self.class_.concrete(1, 1)
        self.assertEqual(y, 1)


class TestChild(BaseTests):

    def setUp(self):
        super(TestChild, self).setUp()
        self.class_ = Child()

    def test_concrete_returns_x_plus_1(self):
        x, _ = self.class_.concrete(1, 1)
        self.assertEqual(x, 2)

This approach seems to work, but I'm wondering if it's the most elegant and scalable option.

Kyle
  • 35
  • 3
  • this has already been answered here i believe. https://stackoverflow.com/questions/9757299/python-testing-an-abstract-base-class The tl;dr is that you can use `unittests.mock.patch` to clear all abstract methods from the base class in order to instantiate it. – ATOMP Jan 04 '20 at 22:37

0 Answers0