9 服务层
本章阐述了服务层,即中间层。
9.1 定义服务
服务层是网站的核心,它接收来自多个来源的请求,访问作为网站DNA的数据,并返回响应。
常见的服务模式包括以下组合:
- 创建/检索/更改(部分或全部)/删除
- 一件事/多件事
在 RESTful 路由器层,名词是资源。在本书中,我们的资源最初将包括隐形生物(想象中的生物)和人(隐形生物探险家)。
以后,我们还可以定义类似的相关资源:
- 地点
- 事件(如探险、目击等)
9.2 布局
以下是当前的文件和目录布局:
main.py
web
├── __init__.py
├── creature.py
├── explorer.py
service
├── __init__.py
├── creature.py
├── explorer.py
data
├── __init__.py
├── creature.py
├── explorer.py
model
├── __init__.py
├── creature.py
├── explorer.py
fake
├── __init__.py
├── creature.py
├── explorer.py
└── test
9.3 函数
让我们从 creature.py 开始。在这一点上,explorer.py 的需求几乎相同,我们可以借用几乎所有的东西。我们很想编写一个服务文件来处理这两个文件,但几乎不可避免的是,在某些时候我们需要以不同的方式处理它们。
另外,在这一点上,服务文件几乎就是一个直通层。在这种情况下,一开始就增加一些额外的结构,以后就会有所回报。就像第8章中的 web/creature.py和web/explorer.py,我们将为这两个文件定义服务模块,并暂时将它们与相应的假数据模块挂钩。
service/creature.py
from models.creature import Creature
import fake.creature as data
def get_all() -> list[Creature]:
return data.get_all()
def get_one(name: str) -> Creature | None:
return data.get(id)
def create(creature: Creature) -> Creature:
return data.create(creature)
def replace(id, creature: Creature) -> Creature:
return data.replace(id, creature)
def modify(id, creature: Creature) -> Creature:
return data.modify(id, creature)
def delete(id, creature: Creature) -> bool:
return data.delete(id)
service/explorer.py
from models.explorer import Explorer
import fake.explorer as data
def get_all() -> list[Explorer]:
return data.get_all()
def get_one(name: str) -> Explorer | None:
return data.get(name)
def create(explorer: Explorer) -> Explorer:
return data.create(explorer)
def replace(id, explorer: Explorer) -> Explorer:
return data.replace(id, explorer)
def modify(id, explorer: Explorer) -> Explorer:
return data.modify(id, explorer)
def delete(id, explorer: Explorer) -> bool:
return data.delete(id)
9.4 测试
现在,代码库正在逐渐充实,是引入自动测试的好时机,让我们创建一些目录:
- test:顶级目录,与web, service, data和model目录并列。
- unit: 测试单个函数,但不跨层。
- web: 网络层单元测试。
- service: 服务层单元测试。
- data:数据层单元测试。
- unit: 测试单个函数,但不跨层。
- full: 也称为端到端或合约测试,这些测试同时跨越所有层。它们涉及网络层的 API 端点。
这些目录有test_前缀或_test 后缀,供pytest使用 。
在测试之前,需要对 API 的设计做出一些选择。如果找不到匹配的 Creature 或 Explorer,get_one() 函数应该返回什么?可以返回 None,或者引发异常。没有一个内置的Python异常类型可以直接处理缺失值:
- TypeError可能是最接近的,因为 None与Creature 是不同的类型。
- ValueError 更适用于给定类型的错误值,但我想你也可以说,向 get_one(id)传递一个缺失的字符串 id 也符合条件。
- 如果你真的需要,也可以定义自己的MissingError。
test/unit/service/test_creature.py
from model.creature import Creature
from service import creature as code
sample = Creature(name="yeti",
country="CN",
area="Himalayas",
description="Hirsute Himalayan",
aka="Abominable Snowman",
)
def test_create():
resp = code.create(sample)
assert resp == sample
def test_get_exists():
resp = code.get_one("yeti")
assert resp == sample
def test_get_missing():
resp = code.get_one("boxturtle")
assert data is None
执行:
$ pytest -v test/unit/service/test_creature.py
test_creature.py::test_create PASSED [ 16%]
test_creature.py::test_get_exists PASSED [ 50%]
test_creature.py::test_get_missing PASSED [ 66%]
======================== 3 passed in 0.06s =========================
参考资料
- 软件测试精品书籍文档下载持续更新 https://github.com/china-testing/python-testing-examples 请点赞,谢谢!
- 本文涉及的python测试开发库 谢谢点赞! https://github.com/china-testing/python_cn_resouce
- python精品书籍下载 https://github.com/china-testing/python_cn_resouce/blob/main/python_good_books.md
- Linux精品书籍下载 https://www.cnblogs.com/testing-/p/17438558.html
9.5 其他服务层内容
我们现在正处于堆栈的中间部分--真正定义网站目的的部分。到目前为止,我们只用它将网络请求转发到(下一章的)数据层。
到目前为止,本书以迭代的方式开发了网站,为今后的工作打下了最基本的基础。当你对你所拥有的、你所能做的以及用户可能需要的有了更多了解后,你就可以进行扩展和尝试。有些想法可能只对大型网站有益,但这里有一些技术性的网站辅助想法:
- Logging
- Metrics
- Monitoring
- Tracing
9.5.1 Logging
FastAPI会记录每次对端点的API调用,包括时间戳、方法和 URL,但不会记录通过正文或标头传递的任何数据。
9.5.2 指标、监控和可观察性
如果你运行一个网站,你可能想知道它的运行情况。对于 API 网站,你可能想知道哪些端点正在被访问、有多少人在访问等等。对这些因素的统计称为度量,收集度量是监控或可观察性。
时下流行的度量工具包括用于收集度量数据的Prometheus和用于显示度量数据的Grafana。
9.5.3 跟踪
您的网站性能如何?常见的情况是,度量指标总体良好,但某些地方或某些地方的结果令人失望。或者整个网站一团糟。无论哪种情况,有一个工具可以测量 API 调用从头到尾所需的时间--不仅是整体时间,还包括每个中间步骤的时间,这非常有用。如果某项工作进展缓慢,就可以找到链条中的薄弱环节。这就是跟踪。
一个新的开源项目采用了早期的跟踪产品(如 Jaeger),并将其命名为 OpenTelemetry。它有一个Python API,并至少与FastAPI 进行了一次集成。
9.5.4 其他
除此以外,我们的域密码和与之相关的任何内容又是怎样的呢?除了探索者和生物的基本细节外,你还想做什么?你可能会想出需要修改模型和其他层的新想法。以下是一些你可以尝试的想法:
- 探险者与他们寻找的生物的链接
- 目击数据
- 探险
- 照片和视频
- 大脚野人马克杯和T恤衫
9.6 小结
在本章中,你复制了网络层中的一些函数,并移动了它们所使用的假数据。目的是启动新的服务层。到目前为止,这个过程都是按部就班地进行的,但在此之后,它还会不断发展和变化。下一章将构建最终的数据层,形成一个真正的实时网站。
标签:服务,explorer,get,FastAPI,py,test,data,creature From: https://www.cnblogs.com/testing-/p/18242828