Sentry 开发者贡献指南 - 测试技巧

作为 CI 流程的一部分,我们在 Sentry 运行了多种测试。
本节旨在记录一些 sentry 特定的帮助程序,
并提供有关在构建新功能时应考虑包括哪些类型的测试的指南。
获取设置
验收和 python 测试需要一组有效的 devservices。
建议使用 devservices 来确保所需要的服务正在运行。
如果您还使用本地环境进行本地测试,您将需要使用 --project 标志将本地测试卷与测试套件卷分开:
# 关闭本地测试服务。
sentry devservices down
# 打开带有 test 前缀的服务以使用单独的容器和卷
sentry devservices up --project test
# 验证测试容器是否正确出现
docker ps --format '{{.Names}}'
# 稍后当您完成运行测试并想再次运行本地服务器时
sentry devservices down --project test && sentry devservices up
使用 --project 选项时,您可以确认哪些容器正在运行 docker ps。
每个正在运行的容器都应该以 test_ 为前缀。
有关管理服务的更多信息,请参阅 devservices docs 部分。
Python 测试
对于 python 测试,我们使用 pytest 和 Django 提供的测试工具。
在此基础之上,我们添加了一些基本测试用例(在 sentry.testutils.cases 中)。
端点集成测试是我们大部分测试套件的重点所在。
这些测试帮助我们确保我们的 customers、integrations 和前端应用程序的 API 继续以预期的方式工作。
您应该努力包含涵盖各种用户角色、跨组织/团队访问场景以及无效数据场景的测试,因为这些在手动测试时经常被忽略。
运行 pytest
您可以根据更改的范围使用 pytest 运行单个目录、单个文件或单个测试:
# 对整个目录运行测试
pytest tests/sentry/api/endpoints/
# 对目录中匹配模式的所有文件运行测试
pytest tests/sentry/api/endpoints/test_organization_*.py
# 从单个文件运行测试
pytest tests/sentry/api/endpoints/test_organization_group_index.py
# 运行单个测试
pytest tests/snuba/api/endpoints/test_organization_events_distribution.py::OrganizationEventsDistributionEndpointTest::test_this_thing
# 在匹配子字符串的文件中运行所有测试
pytest tests/snuba/api/endpoints/test_organization_events_distribution.py -k method_name
pytest 的一些常用选项是:
-k通过子字符串过滤测试方法/类。-s在运行测试时不要捕获标准输出。
有关更多使用选项,请参阅 pytest 文档。
在测试中创建数据
Sentry 还添加了一套 factory 辅助方法,可帮助您构建数据以针对其编写测试。
sentry.testutils.factories 中的工厂方法可用于我们所有的测试套件类。
使用这些方法来建立所需的组织、项目和其他基于 postgres 的状态。
您还应该使用 store_event() 以类似于应用程序在生产中所做的方式存储事件。
存储事件需要您的测试继承自 SnubaTestCase。
使用 store_event() 时,请注意在事件上设置过去的 timestamp。
省略时,timestamp 将使用 'now',这可能会导致由于 timestamp 边界而无法选择事件。
from sentry.testutils.helpers.datetime import before_now
from sentry.utils.samples import load_data
def test_query(self):
data = load_data("python", timestamp=before_now(minutes=1))
event = self.store_event(data, project_id=self.project.id)
设置选项和功能标志
如果您的测试是针对带有功能标记的端点,或者需要设置特定选项。
您可以使用辅助方法将配置数据更改为正确的状态:
def test_success(self):
with self.feature('organization:new-thing'):
with self.options({'option': 'value'}):
# Run test logic with features and options set.
# Disable the new-thing feature.
with self.feature({'organization:new-thing': False}):
# Run you logic with a feature off.
外部服务
使用 responses 库为您的代码发出的出站 API 请求添加存根响应。
这将帮助您相对轻松地模拟成功和失败的场景。
可靠地使用时间
在编写与摄取事件相关的测试时,我们必须在事件的约束内操作不能超过 30 天。
因为所有事件都必须是最近的,所以我们不能使用传统的时间冻结策略在测试中获得一致的数据。
我们不是选择任意的时间点,而是从现在开始向后工作,并且有一些辅助函数可以这样做:
from sentry.testutils.helpers.datetime import before_now, iso_format
five_min_ago = before_now(minutes=5)
iso_timestamp = iso_format(five_min_ago)
这些函数生成 datetime 对象,以及相对于当前的 ISO 8601 格式的 datetime 字符串,
使您能够在已知时间偏移处拥有事件,而不会违反 relay 强加的 30 天限制。
在测试中检查 SQL 查询
将以下内容添加到项目根目录中的 conftest.py 中:
import itertools
from django.conf import settings
from django.db import connection, connections, reset_queries
from django.template import Template, Context
@pytest.fixture(scope="function", autouse=True)
def log_sql():
reset_queries()
settings.DEBUG = True
yield
time = sum([float(q["time"]) for q in connection.queries])
t = Template(
"{% for sql in sqllog %}{{sql.sql|safe}}{% if not forloop.last %}\n\n{% endif %}{% endfor %}"
)
queries = list(itertools.chain.from_iterable([conn.queries for conn in connections.all()]))
log = t.render(Context({"sqllog": queries, "count": len(queries), "time": time}))
print(log)
现在,在测试期间执行的所有 SQL 都将打印到标准输出。
建议使用 pytest 的 -k 选择器缩小输出范围。另请注意,您需要通过 -s 来查看标准输出。
验收测试
我们的验收测试利用 selenium 和 chromedriver 来模拟用户使用前端应用程序和整个后端堆栈。
我们在 Sentry 使用验收测试有两个目的:
- 涵盖仅通过端点测试或仅使用
Jest无法涵盖的工作流程。 - 通过我们的视觉回归
GitHub Actions为视觉回归测试准备快照。
验收测试可以在 tests/acceptance 中找到,并使用 pytest 在本地运行。
运行验收测试
当您运行验收测试时,webpack 将自动运行以构建静态资资源。
如果您在创建或修改验收测试时更改 Javascript 文件,
则每次更改后都需要 rm .webpack.meta 以触发静态资源的重建。
# 运行单个验收测试。
pytest tests/acceptance/test_organization_group_index.py \
-k test_with_onboarding
# 运行带有头的浏览器,以便您可以观看它。
pytest tests/acceptance/test_organization_group_index.py \
--no-headless=true \
-k test_with_onboarding
# 打开每个 snapshot image
SENTRY_SCREENSHOT=1 VISUAL_SNAPSHOT_ENABLE=1 \
pytest tests/acceptance/test_organization_group_index.py \
-k test_with_onboarding
如果您看到:
WARNING: Failed to gather log types: Message: unknown > command: Cannot call non W3C standard command while in W3C mode
则表示Webpack未正确编译资源。
定位元素
因为我们使用 emotion,所以我们的类名通常对浏览器自动化没有用。
相反,我们自由地使用 data-test-id 属性来定义浏览器自动化和 Jest 测试的 hook 点。
处理异步动作
我们所有的数据都异步加载到前端,验收测试需要考虑各种延迟和响应时间。
我们倾向于使用 selenium 的 wait_until* 特性来轮询 DOM,直到元素出现或可见。
我们不使用 sleep()。
视觉回归
像素很重要,因此我们使用视觉回归来帮助捕捉 Sentry 渲染方式的意外变化。
在验收测试期间,我们捕获屏幕截图并将您的拉取请求中的屏幕截图与批准的基线进行比较。
虽然我们对视觉回归有相当广泛的覆盖,但仍有一些重要的盲点:
- 悬停(
Hover)卡片与悬停状态 - 模态窗口
- 图表和数据可视化
所有这些组件和交互通常不包含在可视化快照中,您在处理其中任何一个时都应该小心。
处理不断变化的数据
因为视觉回归比较图像快照,而且我们数据的很大一部分处理时间序列数据,
所以我们经常需要用 'fixed' 数据替换基于时间的内容。
您可以使用 getDynamicText 帮助程序为依赖于当前时间或变化
过于频繁而无法包含在可视快照中的组件/数据提供固定内容。
Jest 测试
我们的 Jest 套件涵盖为前端组件提供功能和单元测试。
我们更喜欢编写与组件交互并观察结果(导航、API 调用)的功能测试,
而不是检查 prop 传递和 state 突变。
请参阅 Frontend Handbook 了解更多 Jest 测试技巧。
# Run jest in interactive mode
yarn test
# Run a single test
yarn test tests/js/spec/views/issueList/overview.spec.js
API Fixtures
因为我们的 Jest 测试在没有 API 的情况下运行,
所以我们有各种 fixture 构建器可用于帮助生成 API 响应有效负载。
TestStubs 全局包括 tests/js/sentry-test/fixtures/ 中的所有 fixture 函数。
您还应该使用 MockApiClient.addMockResponse() 来设置您的组件将进行的 API 调用的响应。未能模拟端点将导致测试失败。
CI 中的 Kafka 测试
Snuba 测试套件 (.github/workflows/snuba-integration-test.yml) 是唯一真正让 Kafka 在 CI 中运行的测试套件。
如果您有一个需要 Kafka 运行的测试,那么这些测试需要嵌套在 Snuba 测试文件夹 (tests/snuba/) 下。
如果不这样做,您的测试将超时并在 GH actions 中被取消。
更多
Sentry 开发者贡献指南 - 测试技巧的更多相关文章
- Sentry 开发者贡献指南 - 后端服务(Python/Go/Rust/NodeJS)
内容整理自官方开发文档 系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Map ...
- Sentry 开发者贡献指南 - SDK 开发(事件负载)
内容整理自官方开发文档 系列 Docker Compose 部署与故障排除详解 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentr ...
- Sentry 开发者贡献指南 - SDK 开发(性能监控:Sentry SDK API 演进)
内容整理自官方开发文档 本文档的目标是将 Sentry SDK 中性能监控功能的演变置于上下文中. 我们首先总结了如何将性能监控添加到 Sentry 和 SDK, 然后我们讨论 identified ...
- Sentry 开发者贡献指南 - Feature Flag
功能 flag 在 Sentry 的代码库中声明. 对于自托管用户,这些标志然后通过 sentry.conf.py 进行配置. 对于 Sentry 的 SaaS 部署,Flagr 用于在生产中配置标志 ...
- Sentry 开发者贡献指南 - 数据库迁移
Django 迁移是我们处理 Sentry 中数据库更改的方式. Django 迁移官方文档:https://docs.djangoproject.com/en/2.2/topics/migratio ...
- Sentry 开发者贡献指南 - 前端 React Hooks 与虫洞状态管理模式
系列 Sentry 开发者贡献指南 - 前端(ReactJS生态) Sentry 开发者贡献指南 - 后端服务(Python/Go/Rust/NodeJS) 什么是虫洞状态管理模式? 您可以逃脱的最小 ...
- Sentry 开发者贡献指南 - SDK 开发(性能监控)
内容整理于官方开发文档 系列 Docker Compose 部署与故障排除详解 K8S + Helm 一键微服务部署 Sentry 开发者贡献指南 - 前端(ReactJS生态) Sentry 开发者 ...
- Sentry 开发者贡献指南 - Django Rest Framework(Serializers)
Serializer 用于获取复杂的 python 模型并将它们转换为 json.序列化程序还可用于在验证传入数据后将 json 反序列化回 Python 模型. 在 Sentry,我们有两种不同类型 ...
- Sentry 开发者贡献指南 - 配置 PyCharm
概述 如果您使用 PyCharm 进行开发,则需要配置一些内容才能运行和调试. 本文档描述了一些对 sentry 开发有用的配置 配置 Python 解释器:(确保它是 venv 解释器)例如 ~/v ...
随机推荐
- CF946B Weird Subtraction Process 题解
Content 有两个数 \(a,b\),执行如下操作: 如果 \(a,b\) 中有一个数是 \(0\),结束操作,否则跳到操作 \(2\). 如果 \(a\geqslant 2b\),那么 \(a\ ...
- CF999A Mishka and Contest 题解
Content 能力值为 \(k\) 的小 M 参加一次考试,考试一共有 \(n\) 道题目,每道题目的难度为 \(a_i\).小 M 会选择两头中的一道难度不超过他的能力值题目去做,每做完一道,这道 ...
- 贪心——122.买卖股票的最佳时机II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多笔交易(你必须在再次 ...
- Python3 shevel模块,更高级的json序列化数据类型模块(比pickle更高级)
直接将数据类型以字典的格式 存到文件中去. 直接.get读取出来,
- 将本地的react项目代码打包到服务器
打包过程 连接服务器 ssh root@xx.xx.xx.xx(服务器IP) 定位到当前项目目录 cd /path/projectName 更新代码到服务器 git pull 执行打包命令(这里我创建 ...
- Ubuntu Server服务器上架设Git Server服务器
1.设置公钥 ubuntu:/home/git$ ssh-keygen -t rsa #生成密钥 这里会提示输入密码,我们不输入直接回车即可. 然后用刚生成公钥/home/git/.ssh/id_rs ...
- 【LeetCode】628. Maximum Product of Three Numbers 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 方法一:排序 日期 题目地址:https://lee ...
- 【LeetCode】137. Single Number II 解题报告(Python)
[LeetCode]137. Single Number II 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/single- ...
- [LeetCode]621. Task Scheduler 任务安排 题解
题目描述 给定一个char数组,代表CPU需要做的任务,包含A-Z,不用考虑顺序,每个任务能在1个单位完成.但是有规定一个非负整数n代表两个相同任务之间需要至少n个时间单位.球最少数量的时间单位完成所 ...
- 4 种主流的 API 架构风格对比
1RPC:调用另一个系统的函数 RPC 的工作机制 客户端调用一个远程的过程,将参数和附加信息序列化为消息,然后将消息发送到服务端.服务端在接受到消息后,将信息的内容反序列化,执行所请求的操作,然后将 ...