在上一篇文章中,我们确实使用假设创建了一些检验来为我们生成输入日期。在那篇文章中,有一个验证类来验证密码。我在每个测试中都会检查API调用的回复。使用python进行API response验证并不困难。我解释一下。
假设我们有一个返回一些用户数据的API。例如,我可以使用ID调用函数getPerson并检索以下数据:
{
"name": "testuser",
"age": 34,
"interest": "testing"
}
response是带有某些字段的json文件。名称至少应包含8个字符,并且不能超过12个字符。年龄是整数。系统中的用户必须年满21岁,因此18岁是无效的。interest的值是以下值之一:“testing”, “programming”, “agile”.
现在,我可以使用以下python代码检查所有值:
class ReplyValidator(object):
def check_name(self, name):
if len(name) < 8:
return False
elif len(name) > 12:
return False
return True
def check_age(self, age):
if age < 21:
return False
return True
def check_interest(self, interest):
if interest not in ["testing", "programming", "agile"]:
return False
return True
class Reply():
def __init__(self, data):
self.name = data["name"]
self.age = data["age"]
self.interest = data["interest"]
@property
def is_valid(self):
return all([
ReplyValidator().check_name(self.name),
ReplyValidator().check_street(self.street),
ReplyValidator().check_age(self.age),
ReplyValidator().check_interest(self.interest)
])
我也创建了一些单元测试来测试我们的验证类。我仍然是一名测试人员,所以我也测试自己的代码。
单元测试我自己的代码
from line import Reply
def test_a_valid_reply():
reply_data = dict(name="testuser",
street="testing street",
age=34,
interest="testing")
reply = Reply(reply_data)
assert reply.is_valid
def test_an_invalid_name():
reply_data = dict(name="test",
street="testing street",
age=34,
interest="testing")
reply = Reply(reply_data)
assert not reply.is_valid
def test_an_invalid_age():
reply_data = dict(name="test",
street="testing street",
age=10,
interest="testing")
reply = Reply(reply_data)
assert reply.is_valid
在python中使用抽象方法 代码很简单。但是,如果有额外的验证,则必须创建验证并添加额外的检查。您不必编写大量代码来检查它会不好吗?可以使用描述符技术编写验证类。
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
首先,我们创建一个继承自ABC类的BaseValidator类。因此,我可以创建一个抽象方法。从此类继承的所有类都必须实现验证功能。
描述符可以绑定变量,例如python中的@property装饰器。我们可以创建一些数据类来保存值并检查该值是否有效。描述符的设置器首先调用一个函数来验证输入。BaseValidator的所有子类都必须实现此功能。现在界面已更改。如果验证失败,则会引发异常。
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}')
我创建了3个示例类。String,Integer和OneOf类。String类具有最小和最大长度。验证器功能检查新值是否在最小和最大长度之间。
Integer类具有一个最小参数。验证功能检查新值是否大于此最小参数。
OneOf类很特殊。它接收可能的(字符串)值列表。验证功能检查新值是否为可能的值之一。
使用验证程序进行API回复验证 现有代码现在应该更改。让我们以最小的变化尝试一下。
class ReplyValidator(object):
name = String()
age = Integer()
interest = OneOf(["testing", "programming", "agile"])
class Reply():
def __init__(self, data):
self.name = data["name"]
self.age = data["age"]
self.interest = data["interest"]
@property
def is_valid(self):
validator = ReplyValidator()
validator.name = self.name
validator.age = self.age
validator.interest = self.interest
return True
两个测试用例需要更新。输入无效时,代码将引发异常。
def test_an_invalid_name():
reply_data = dict(name="test",
street="testing street",
age=34,
interest="testing")
reply = Reply(reply_data)
with pytest.raises(ValueError):
not reply.is_valid
def test_an_invalid_age():
reply_data = dict(name="testuser",
street="testing street",
age=10,
interest="testing")
reply = Reply(reply_data)
with pytest.raises(ValueError):
reply.is_valid
代码再次更改。不再需要is_valid方法。“框架”现在可以验证所有数据。如果验证失败,则会引发错误。因此我们的代码如下所示:
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"]
该代码无需额外检查即可验证数据。现在可以使用Reply类验证API的response。将真实的API答复作为输入参数。使用python进行API response验证并不困难。这正是我要进行API测试所需要的