[英]Python: Testing abstract class with concrete implementation details
I have a class containing a mixture of @abstractmethod
s and normal implementation methods, and I'm wondering how I should go about testing the normal implementations.我有一个 class 包含@abstractmethod
和正常实现方法的混合,我想知道我应该如何 go 测试正常实现。
Quick Example: I'd like to test the zoo_str
method, even though it depends on the abstract description
method.快速示例:我想测试zoo_str
方法,即使它依赖于抽象description
方法。 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
).如果我有 100 只动物,那么在 Lion class、Antelope class、Hippo class 等中编写测试似乎有些矫枉过正。最好的方法是什么——我的直觉告诉我应该尝试模拟description
,但我无法实例化 class,如果抽象方法是私有的 ( _description
),这就会分崩离析。
class Animal:
@abstractmethod
def description(self) -> str:
pass
def zoo_str(self) -> str:
return self.description() + "Get more info at zoo.com!"
Just create a subclass.只需创建一个子类。
class TestAnimal(Animal):
def description(self):
return "foo"
assert TestAnimal().zoo_str() == "fooGet more info at zoo.com!"
You can simply use multiple inheritance:您可以简单地使用多个 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!"
Here is a mock-using variant (based on https://stackoverflow.com/a/63777635 ) showing how to test against all Animal
subclasses:这是一个模拟使用变体(基于https://stackoverflow.com/a/63777635 )展示了如何针对所有Animal
子类进行测试:
@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!"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.