Pytest 测试失败,因为在使用 pytest 测试子类时找不到 python 超类属性

问题描述 投票:0回答:1

请强调,这不是重复的,因为我已阅读此处的所有 pytest 子类问题,但没有一个解决我遇到的错误。

我的问题简而言之:我对一个子类进行了 pytest,该子类失败了,因为测试依赖于超类属性来运行,但是 pytest 在子类的这些属性上引发了 AttributeError,而这些属性在超类中得到了很好的定义

我有两个类 Entity 一个基类,用于处理 id 生成和常见错误的错误处理 一旦发生业务规则验证错误,实体就会将其添加到错误列表中,并且在其 init 类中,如果错误列表不为空,则会引发 ValueError

实体.py

from abc import ABC
import uuid

# a util class containing basic validation bool functions. ex: is_valid_datetime
from util import Validator

class Entity(ABC):
    id: str
    errors: list[dict]

    def __init_(self) -> None:
        self.id = ""
        self.errors = []

        if not self.id:
            self.id = uuid.uuid4().hex

        self.validate()

    def validate(self) -> None:
        if len(self.errors) > 0:
           raise ValueError(self.errors)

    # simple example of a validation function
    def validate_is_datetime(self, attr_name: str, attr_value: datetime) -> bool:
        if Validator.is_valid_datetime(attr_value)
            return True
        else:
            self.errors.append(
                {
                    "type": "datetime",
                    "loc": f"Entity, {attr_name}",
                    "msg": "Attribute should be a valid datetime",
                    "input": attr_value
                }
            )

继承自实体的 Product 类。 产品.py

from entity import Entity

class Product(Entity):
    name: str
    price: str

    def __init__(name: str, price: str) -> None:
        self.name = name
        # example of a validation that will fail during instantiation
        # I need it to fail to showcase the problem I'm having
        self.validate_is_datetime(name)

        self.price = price

        super().__init__()

使用 pytest

测试我的课程

Pytest 装置 conftest.py

import pytest
from entity import Entity
from product import Product

@pytest.fixture(scope="class")
def entity():
    return Entity()

@pytest.fixture(scope="class")
def product():
    return Product(name="Iphone 8", price="150")

测试产品域实体 test_product.py

# simple test to ensure correct instantiation
def test_name_is_iphone8(product: Product) -> None:
    assert product.name == "Iphone 8"

我首先在 test_product.py 中运行产品模型的测试

pytest

现在显然按照之前的定义,我预计测试会失败,因为在产品实例化期间会引发 ValueError,正如我在产品 init `self.validate_is_valid_datetime(self.name), name: str 中调用的那样,name: str 不能是有效的日期时间。

结果是测试失败,好的,但不会引发 ValueError,而是引发 AttributeError,指出 product 对象没有错误属性。因此 pytest 不会出现错误是在超类 Entity 中定义的,并且应该在继承它的 Product 中可用。

python-3.x inheritance pytest fastapi attributeerror
1个回答
0
投票

抱歉,我发现了我犯的错误(这个项目有点太仓促了):

在 Product init 方法中,我在 Product.

init
() 函数末尾调用 super().__init__()

   class Product(Entity):
       ...
       def __init__(name: str, price: str) -> None:
           self.name = name
           #the test that fails
           self.validate_is_datetime(self.name) #this function depends on errors attr that has yet to be initialized by the super class
           self.price = price
           super().__init__() # The errors attr is only initialized at this point so all functions using before this call will raise AttributeError

虽然应该更快地调用它,因为实体 init 方法会初始化错误属性。在Python中,如果类成员未初始化,Python在调用它时将无法识别它。所以product.py init 方法的代码应该是:

   class Product(Entity):
       ...
       def __init__(name: str, price: str) -> None:
           # call it first to initialize errors attr needed in validation methods
           super().__init__() 
           self.name = name
           #the test that fails
           self.validate_is_datetime(self.name)
           self.price = price

现在我怀疑其他人会犯同样的愚蠢错误,但是如果您在测试子类时遇到 pytest 属性错误,请确保您的属性已使用值很好地初始化,单独定义它(例如:name:str)是行不通的。 如果您的 attr 在超类中初始化,请确保在适当的时间调用它的 init 方法,以在使用所需属性之前对其进行初始化

© www.soinside.com 2019 - 2024. All rights reserved.