编写功能测试的目的
验证应用的行为和期望一致的测试
确认异常修复的测试(增加测试覆盖率)
想想一个场景,因为接口需要增加一些功能,而更改了一些代码。
那么修改的代码会不会对之前的功能有影响呢?测试就来了。
并且,良好的编写测试习惯,持续地写测试写文档写代码是必备的。更改代码也更加方便(重构),只用相同的测试代码即可。而且还能提升代码的可读性,测试代码也是功能的描述。
测试的分类
- 单元测试(unit test)# 主要测函数
- 功能测试(function test)# 主要测某些代码段完整的功能
- 集成测试(integration test) # 主要在线上环境测试
- 负载/压力测试 (load test) # 大家比较熟悉
- 端到端测试 (end-to-end test) # 完整的测试产品
本文主要讲解功能测试实例的编写。
在python中编写功能测试代码
主要分为两部分,客户端测试和服务器端测试。
目的都是为了检测自己写的代码是否实现了自己想要的功能。
功能测试组要注意的点:
功能测试都不占用网络服务资源,请求都直接模拟网络资源
客户端测试可以用在哪里呢?
带有请求的地方都可以:
爬虫
调用第三方的接口(OSS, 数据库, AI服务等)
PS: 为了提升代码质量,所有代码都会使用静态注释,你的python version
需要 >= 3.5
如何实现网络资源请求的模拟呢?这时候,我们的 mock 就要出场了。
1. 客户端测试 request_mock
首先,我们编写一个简单的客户端,当作我们用来测试的客户端 client.py
,代码如下:
import typing
from urllib import parse
import requests
MyResponse = typing.Dict[str, typing.List[str]]
class MySpider:
"""拼接返回的id"""
def __init__(self, url="http://example.com") -> None:
self.url: str = url
self.return_base_url: str = "http://shop.com/id/"
def get_data(self):
try:
response: requests.Response = requests.get(self.url)
except requests.exceptions.ConnectionError:
# 链接超时
return self._handle_data()
else:
response.raise_for_status() # 检查请求状态值200
data = response.json()
return self._handle_data(data)
def _handle_data(self, data=None) -> MyResponse:
"""处理请求的数据"""
if data:
return_data: typing.List[str] = []
all_id = data.get("all_id", [])
for goods_id in all_id:
return_data.append(parse.urljoin(self.return_base_url, goods_id))
return {
"data": return_data}
return {
"data": []}
客户端简单的实现了一个请求网站并处理返回数据的逻辑.
那么,开始测试我们的客户端吧!
记住:这是功能测试,与网络资源访问无关,我们只需要测试功能逻辑!其余第三方对象用模拟对象即可!
一般的对象,unittest
自带的 mock
对象就能满足。那么如何网络模拟对象的实现呢?这时候,我们的 requests_mock
就要登场了。
它会实现对请求的拦截,以此达到我们想要的效果。
测试代码 test_client.py
如下:
import unittest
from unittest import mock
import requests
import requests_mock
from client import MySpider, MyResponse
class TestMySpider(unittest.TestCase):
def setUp(self) -> None:
self.spider: MySpider = MySpi