Home > Software engineering >  Python: Testing abstract class with concrete implementation details
Python: Testing abstract class with concrete implementation details

Time:03-19

I have a class containing a mixture of @abstractmethods and normal implementation methods, and I'm wondering how I should go about testing the normal implementations.

Quick Example: I'd like to test the zoo_str method, even though it depends on the abstract description method. If I have 100 animals, it seems like overkill to write a test in the Lion class, the Antelope class, the Hippo class, etc. What's the best way to do this -- my intuition says I should try to mock description, but I can't instatntiate the class and this falls apart if the abstract method is private (_description).

class Animal:
    @abstractmethod
    def description(self) -> str:
        pass

    def zoo_str(self) -> str:
         return self.description()   "Get more info at zoo.com!"

CodePudding user response:

Just create a subclass.

class TestAnimal(Animal):
    def description(self):
        return "foo"


assert TestAnimal().zoo_str() == "fooGet more info at zoo.com!"

CodePudding user response:

You can simply use multiple inheritance:

# test_animals.py
import unittest

from animals import Animal


class TestAnimal(unittest.TestCase, Animal):

    def description(self) -> str:
        return "Unittest"

    def test_zoo_str(self) -> None:
        assert self.zoo_str() == "UnittestGet more info at zoo.com!"

CodePudding user response:

Here is a mock-using variant (based on https://stackoverflow.com/a/63777635) showing how to test against all Animal subclasses:

@pytest.mark.parametrize("cls", Animal.__subclasses__())
def test_animals(mocker, cls):
    mocker.patch.multiple(cls, __abstractmethods__=set())
    inst = cls()
    assert inst.zoo_str() == f"{inst.description()}Get more info at zoo.com!"
  • Related