You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Mother Pattern优化VarCharType子类测试代码的最佳实践

解决方案

针对你遇到的两个问题,我们可以通过泛型通用Mother基类实现类型安全的复用,彻底解决长度同步和重复代码问题,完全不需要使用typing.Any。

步骤1:定义泛型基类封装通用逻辑

创建泛型的VarCharMother基类,自动读取目标VarCharType子类的长度限制,同时支持可配置字符集:

import random
import string
from typing import TypeVar, Generic, Type
from your_module import VarCharType  # 替换为实际模块路径

# 绑定到VarCharType子类的泛型变量,保证类型安全
T = TypeVar('T', bound=VarCharType)

class VarCharMother(Generic[T]):
    # 子类必须指定目标类型
    _target_type: Type[T]
    # 默认字符集,可被子类覆盖或调用时传入
    _default_charset: str = string.ascii_uppercase

    @classmethod
    def _generate_string(cls, length: int, charset: str | None = None) -> str:
        """生成指定长度的随机字符串"""
        return ''.join(random.choices(charset or cls._default_charset, k=length))

    @classmethod
    def random_min(cls, charset: str | None = None) -> T:
        """生成符合最小长度要求的随机实例"""
        return cls._target_type(cls._generate_string(cls._target_type._MIN_LENGTH, charset))

    @classmethod
    def random_max(cls, charset: str | None = None) -> T:
        """生成符合最大长度要求的随机实例"""
        return cls._target_type(cls._generate_string(cls._target_type._MAX_LENGTH, charset))

    @classmethod
    def random_with_length(cls, length: int, charset: str | None = None) -> T:
        """生成指定长度的合法随机实例(可选扩展)"""
        if not cls._target_type._MIN_LENGTH <= length <= cls._target_type._MAX_LENGTH:
            raise ValueError(f"Length {length} out of bounds for {cls._target_type.__name__}")
        return cls._target_type(cls._generate_string(length, charset))

步骤2:简化具体Mother类的实现

GivenNameMother和FamilyNameMother只需继承通用基类并指定目标类型,无需重复编写生成逻辑:

from your_module import GivenName, FamilyName

class GivenNameMother(VarCharMother[GivenName]):
    _target_type = GivenName
    # 可选:覆盖默认字符集以支持UTF-8测试
    # _default_charset = string.ascii_uppercase + "àáâãéèêíìîóòôúùûñç"

class FamilyNameMother(VarCharMother[FamilyName]):
    _target_type = FamilyName

核心优势

  1. 解决长度同步问题:
    所有长度参数直接读取目标类的_MIN_LENGTH和_MAX_LENGTH常量,修改GivenName的长度限制时,GivenNameMother会自动同步,无需手动修改测试代码。

  2. 消除重复代码:
    通用基类封装了所有生成逻辑,新增VarCharType子类时,只需创建简单的Mother子类并指定目标类型即可。

  3. 灵活扩展字符集:

    • 可在具体Mother类中覆盖_default_charset默认使用UTF-8字符
    • 也可在调用时临时传入字符集,例如:
      # 用中文生成随机姓氏
      chinese_family_name = FamilyNameMother.random_min(charset="赵钱孙李周吴郑王")
      
  4. 类型安全:
    通过泛型T绑定VarCharType子类,所有方法返回的都是具体的GivenName/FamilyName类型,完全不需要使用typing.Any。

额外优化建议(可选)

由于VarCharType继承自不可变类型str,建议将长度验证逻辑移到__new__方法(str子类的最佳实践):

from abc import ABC, abstractmethod

class VarCharType(str, ABC):
    def __new__(cls, value):
        # 在实例创建前验证长度
        cls._validate_length(value)
        return super().__new__(cls, value)

    @classmethod
    def _validate_length(cls, value: str):
        if not cls._min_length <= len(value) <= cls._max_length:
            raise TypeError(f'Length must be between {cls._min_length} and {cls._max_length}')

    @property
    @classmethod
    @abstractmethod
    def _min_length(cls) -> int:
        pass

    @property
    @classmethod
    @abstractmethod
    def _max_length(cls) -> int:
        pass

这样可避免创建不符合长度要求的实例,让VarCharType的实现更符合Python类型规范。


内容的提问来源于stack exchange,提问作者guibos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 16:13:18