Python Api响应验证封装
基础验证基类
首先,我们创建一个继承自ABC类的BaseValidator类。因此,我可以创建一个抽象方法。从此类继承的所有类都必须实现验证功能。
其中有三个魔法函数,__set__()函数在为对象赋值时,自动传入并执行。
from abc import ABC, abstractmethod class BaseValidator(ABC): @abstractmethod def validate(self, value): pass def __init__(self): self.value = None def __get__(self, obj, objtype): return self.value def __set__(self,obj, value): self.validate(value) self.value = value
创建验证类
然后创建了3个验证示例类。String,Integer和OneOf类。
String类具有最小和最大长度。验证器功能检查新值是否在最小和最大长度之间。
Integer类具有一个最小参数。验证功能检查新值是否大于此最小参数。
OneOf类很特殊。它接收可能的(字符串)值列表。验证功能检查新值是否为可能的值之一。
class OneOf(BaseValidator): def __init__(self, values=list()): self.values = values def validate(self, value): if not isinstance(value, str): raise TypeError(f'{value} should be of type str') if not(value in self.values): raise ValueError(f'{value} should be one of {self.values}') class String(BaseValidator): def __init__(self, min_len = 8, max_len=12): self.min_len = min_len self.max_len = max_len def validate(self, value): if not isinstance(value, str): raise TypeError(f'{value} should be of type str') if len(value) < self.min_len: raise ValueError(f'length of {value} should be at least {self.min_len}') if len(value) > self.max_len: raise ValueError(f'length of {value} should be not bigger than {self.max_len}') class Integer(BaseValidator): def __init__(self, minimum=21): self.minimum = minimum def validate(self, value): if not isinstance(value, int): raise TypeError(f'{value} should be of type int') if value < self.minimum: raise ValueError(f'{value} should be at least {self.minimum}')
构建unittest测试
这里ReplyValidator和Reply写死了,在实际工作中,可以将验证类对象与数据一起传入Reply,在ReplyValidator中循环实例化对象,并以列表返回,再循环赋值验证。
import unittest class ReplyValidator(object): name = String() age = Integer() interest = OneOf(["testing", "programming", "agile"]) class Reply(): def __init__(self, data): self.validator = ReplyValidator() self.validator.name = data["name"] self.validator.age = data["age"] self.validator.interest = data["interest"] class BaiduTest(unittest.TestCase): def setUp(self): pass def test_baidu(self): reply_data = dict(name="test", street="testing street", age=34, interest="testing") reply = Reply(reply_data) def tearDown(self): pass if __name__ == "__main__": unittest.main()