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 ...
随机推荐
- CF981B Businessmen Problems 题解
Content 有一个长度为 \(n\) 的序列和长度为 \(m\) 的序列,两个序列中的元素都有一个编号 \(num\) 和一个值 \(val\),且同一个序列的元素之间的编号互不相同.现在从这两个 ...
- redis查看redis 客户端状态
查看redis客户端连接 redis-cli info clients # Clients connected_clients:6000 client_longest_output_list:0 cl ...
- STL源码剖析-waked_ptr
目录一.提问二. 代码实现2.1 mweak_ptr的具体实现2.2 测试用例一.提问weak_ptr为什么会存在?shared_ptr不是已经有了引用计数吗?具体原因详见模拟实现boost库中的sh ...
- c++之面试题(1)
题目 有十瓶药,每瓶里都装有100片药,其中有八瓶里的药每片重10克,另有两瓶里的药每片重9克.用一个蛮精确的小秤,只称一次,如何找出份量较轻的那两个药瓶? 解法 1.分别给10个药瓶按照斐波那契数列 ...
- c++interview
出自:https://github.com/huihut/interview Github | Docsify 简体中文 | English 关于 本仓库是面向 C/C++ 技 ...
- 【LeetCode】961. N-Repeated Element in Size 2N Array 解题报告(Python & C+++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 字典 日期 题目地址:https://leetcod ...
- 【LeetCode】841. Keys and Rooms 解题报告(Python & C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS BFS 日期 题目地址:https://le ...
- Globally-Robust Neural Networks
目录 概 主要内容 代码 Leino K., Wang Z. and Fredrikson M. Globally-robust neural networks. In International C ...
- rapidjson解析与构造实例
void rapidjson1(){ rapidjson::StringBuffer s; rapidjson::Writer<rapidjson::StringBuffer> write ...
- 【jvm】06-new一个对象到底占了多少内存?
[jvm]06-new一个对象到底占了多少内存? 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺 ...