RedisInsight E2E 测试框架完全指南:基于 Playwright 的 Chromium 与 Electron 端到端测试
【免费下载链接】RedisInsightRedis GUI by Redis项目地址: https://gitcode.com/GitHub_Trending/re/RedisInsight
本指南系统讲解 RedisInsight 开源仓库中独立的 Playwright E2E 测试套件(位于tests/e2e-playwright/),涵盖从环境搭建、配置管理、测试编写到并行/串行执行策略的完整实战路径。读完本文,你将掌握如何在本仓库中为 RedisInsight 的 Web 界面(Chromium)与桌面客户端(Electron)编写、调试和运行可靠的端到端测试,并理解其基于 Page Object Model、项目(Project)分层与 fixture 体系的底层设计原理。
测试套件定位与文档体系
RedisInsight 的 E2E 测试经历了从旧版向新版演进的历程,tests/e2e-playwright/下的 README 明确将其定义为 "RedisInsight E2E Tests v2",即独立的 Playwright E2E 测试套件(Standalone Playwright E2E test suite),与仓库根目录下另一套基于 Jest 的redisinsight/test/api测试(可参考 test/api/README.md)形成互补:API 测试聚焦后端逻辑,而本套件聚焦真实 UI 交互与桌面端行为。
该目录的 README 同时承担了「入口导航」职责,它维护了两份关键配套文档:
| 文档 | 用途 |
|---|---|
| tests/e2e-playwright/TEST_PLAN.md | 测试覆盖状态与优先级清单,按功能区域(数据库管理、Browser、Workbench、CLI、Pub/Sub、Analytics、Settings、Vector Search、Cloud、Sentinel、RDI 等)组织,用 ✅(已实现)/ 🔲(未实现)/ ⏳(进行中)/ ⏸️(跳过)标记每个用例的进度 |
| .ai/skills/e2e-testing/SKILL.md | 编写测试的标准与模式约定(编码规范、命名、断言风格等),是新增测试前必读的规范文档 |
TEST_PLAN.md不仅是状态清单,还直接映射到测试文件——例如 Vector Search 部分为每个用例标注了对应 spec 文件路径(如tests/serial/vector-search/query/query-editor.spec.ts),测试用例标题要求与 spec 文件中的实际测试标题完全一致,便于按图索骥。
内置 AI 命令(Augment AI)
README 提供两个与 Augment AI 配合使用的命令,用于生成与修复测试:
| 命令 | 说明 |
|---|---|
@e2e-generate <url> [focus] | 借助 Playwright MCP 探索 UI 并生成测试 |
@e2e-fix <test-pattern> | 运行测试并修复失败 |
示例:
@e2e-generate http://localhost:8080/browser "add key" @e2e-fix "Analytics > Slow Log"这两个命令在 .ai/commands/e2e-generate.md 与 .ai/commands/e2e-fix.md 中有完整定义:@e2e-generate通过 Playwright MCP 的browser_navigate_Playwright/browser_snapshot_Playwright/browser_click_Playwright逐步探索页面,优先利用data-testid、元素 role、占位符等可访问性信息生成选择器;@e2e-fix则使用npx playwright test --grep "<pattern>" --reporter=list运行目标测试,读取test-results/<test-folder>/error-context.md(含页面快照、错误信息、调用日志)进行诊断,修复后强制要求通过npm run lint && npx tsc --noEmit才能收尾。
环境准备(Prerequisites)
1. 启动 Redis 测试环境(RTE)
所有项目共用同一套 Redis 测试环境(RTE),使用 Docker Compose 一键拉起:
cd tests/e2e docker-compose -f rte.docker-compose.yml up -d该 Compose 文件(tests/e2e/rte.docker-compose.yml)会拉起多种 Redis 拓扑实例,包括不同版本的 standalone、cluster、sentinel、TLS 实例等,端口与 tests/e2e-playwright/example.env 中的OSS_STANDALONE_*、OSS_CLUSTER_*、OSS_SENTINEL_*配置一一对应(例如 standalone 默认在127.0.0.1:8100,cluster 在127.0.0.1:8200,sentinel 在127.0.0.1:28100)。
2. /etc/hosts 配置(本地运行一次性设置)
Cluster 测试尤其依赖 host 解析。集群节点通过cluster-announce-hostname向客户端通告主机名,API 需要在你的宿主机上解析这些名字,因此本地运行时必须追加以下条目:
127.0.0.1 host.docker.internal 127.0.0.1 master-hostname-7-1 master-hostname-7-2 master-hostname-7-3若不配置,集群测试在创建数据库时会失败,报500/errorCode 12500("Server closed the connection.")。
两个易踩的坑(README 特别强调):
- 每一行必须是独立的行,且上一行末尾要换行,否则会拼成
127.0.0.1 existing-entry127.0.0.1 host.docker.internal这样的错误行; - 配置后可用
grep -n "host.docker.internal\|master-hostname" /etc/hosts验证。
值得一提的是,这个问题的根源在源码中有据可查:tests/e2e-playwright/helpers/api.ts 的注释指出,Docker 任务中曾出现的长时卡顿正是因为应用无法解析集群通告的主机名,最终通过在 Compose 文件中修复而非延长重试等待解决。
3. 项目特定启动方式
| 项目 | 启动命令 | 运行测试 |
|---|---|---|
| Chromium | npm run dev:api+npm run dev:ui(两个终端) | npm run test:chromium |
| Electron | npm run package:prod | npm run test:electron |
启动命令在仓库根目录执行;测试命令在
tests/e2e-playwright/目录内执行。
Chromium 模式需要同时跑起 API(默认http://localhost:5540)与 UI(默认http://localhost:8080);Electron 模式则需要先打包出可执行产物,测试时由 Playwright 直接拉起桌面应用。
安装依赖
cd tests/e2e-playwright npm install npx playwright install chromium该目录是独立 npm 包(见 tests/e2e-playwright/package.json),核心依赖包括@playwright/test(^1.61.1)、@faker-js/faker(^10.5.0,用于测试数据生成)、fishery(^2.4.0,用于声明式数据工厂)、dotenv(环境变量加载),并集成了eslint、prettier、husky+lint-staged的完整质量门禁(提交前自动 lint/format 变更的.ts文件)。
配置:环境变量与多环境支持
复制模板并修改为本机环境:
cp example.env .env核心环境变量如下:
| 变量 | 说明 | 默认值 |
|---|---|---|
RI_CLIENT_URL | RedisInsight UI 地址 | http://localhost:8080 |
RI_API_URL | RedisInsight API 地址 | http://localhost:5540 |
RI_ELECTRON_API_URL | Electron 内嵌 API 地址 | http://localhost:5530(见 config/app.ts) |
ELECTRON_EXECUTABLE_PATH | Electron 可执行文件路径(可覆盖默认值) | 平台相关,见下文表格 |
OSS_STANDALONE_* | standalone Redis 连接信息(含 V5/V7/V8/8.8.0/空库/TLS 等多实例) | 127.0.0.1:8100等 |
OSS_CLUSTER_* | cluster Redis 连接信息(含 hostname 通告实例) | 127.0.0.1:8200等 |
OSS_SENTINEL_* | Sentinel 连接信息(含密码与主从组名) | 127.0.0.1:28100等 |
REDIS_SSH_*/SSH_* | SSH 隧道配置(可选,注释状态) | 无 |
多环境支持(ENV 变量)
框架通过ENV环境变量切换配置来源,底层实现在 config/env.ts:
# 本地(默认)—— 加载 .env npm test # CI —— 加载 .env.ci ENV=ci npm test # Staging —— 加载 .env.staging ENV=staging npm test加载优先级为process.env > .env.{ENV} > .env:先加载环境专属文件,再以默认.env兜底且不覆盖已存在的值。currentEnv会导出当前环境名(默认local)。配套的getEnv/getEnvNumber/getEnvOptional帮助函数在变量缺失时抛出明确错误,避免静默使用错误配置。
运行测试:命令速查
package.json 中预置了完整的脚本族:
| 命令 | 说明 |
|---|---|
npm test | 运行全部测试(所有项目) |
npm run test:chromium | 仅运行 Chromium 浏览器测试(parallel + serial) |
npm run test:chromium:headed | 带可见浏览器窗口运行 |
npm run test:chromium:debug | 打开 Playwright Inspector(暂停并逐步执行) |
npm run test:chromium:ui | 打开交互式 UI 测试面板 |
npm run test:electron | 运行 Electron 桌面测试 |
npm run test:electron:headed | 带可见 Electron 窗口运行 |
npm run test:electron:debug | 带 Playwright Inspector 调试 |
npm run test:report | 查看 HTML 测试报告(playwright show-report) |
npm run test:codegen | 录制操作并生成测试代码(playwright codegen http://localhost:8080) |
另有test:chromium:parallel、test:chromium:serial、test:electron:parallel、test:electron:serial用于单独运行某一项目(serial 变体带--no-deps)。
Chromium 浏览器测试
npm test # 运行全部测试 npm run test:chromium # 仅 Chromium 项目 npm run test:chromium:headed # 观察测试执行 npm run test:chromium:debug # 暂停并逐步调试 npm run test:chromium:ui # 交互式运行器Electron 桌面测试
npm run test:electron # 运行全部 Electron 测试 npm run test:electron:headed # 观察应用 npm run test:electron:debug # 用 Inspector 调试自定义可执行文件路径
需要覆盖默认路径(例如自定义构建位置)时:
ELECTRON_EXECUTABLE_PATH="/path/to/your/app" npm run test:electron各平台默认路径:
| 平台 | 默认路径 |
|---|---|
| macOS arm64 | release/mac-arm64/Redis Insight.app/Contents/MacOS/Redis Insight |
| macOS x64 | release/mac-x64/Redis Insight.app/Contents/MacOS/Redis Insight |
| Linux | release/linux-unpacked/redisinsight |
| Windows | release/win-unpacked/Redis Insight.exe |
Electron 测试的关键差异
- 单 worker:Electron 测试固定以 1 个 worker 顺序执行(因为只有一个应用实例);
- 更长的超时:README 提到 Electron 测试默认 120s 超时(浏览器为 60s);不过从 playwright.config.ts 的当前配置看,四个测试项目统一设置了
timeout: 60000,而 Electron 启动器本身在 fixtures/base.ts 中为electron.launch设置了timeout: 60000,这意味着实际以配置文件为准,README 数值可能对应历史版本——动手前请以仓库现状核对; - UI 驱动导航:所有导航都通过 UI 点击完成,保证浏览器与 Electron 行为一致;
- 同一套测试文件:浏览器与 Electron 复用
tests/parallel/与tests/serial/下完全相同的测试文件,仅在运行项目层面区分。
导航方法(Navigation Methods)
为保证跨平台一致性,所有导航均基于 UI 操作。BasePage提供基础导航:
await this.gotoHome(); // 点击 Redis logo → 数据库列表 await this.gotoDatabase(dbId); // 点击数据库 → Browser 页(默认)每个页面对象都有各自的goto()方法,负责导航 + 等待:
await settingsPage.goto(); // 设置页 await browserPage.goto(dbId); // 数据库的 Browser 页 await workbenchPage.goto(dbId); // 数据库的 Workbench 页 await analyticsPage.goto(dbId); // 数据库的 Analytics 页 await pubSubPage.goto(dbId); // 数据库的 Pub/Sub 页InstancePage提供已连接数据库内的页签切换:
await browserPage.navigationTabs.gotoBrowser(); await browserPage.navigationTabs.gotoWorkbench(); await browserPage.navigationTabs.gotoAnalyze(); await browserPage.navigationTabs.gotoPubSub();目录结构总览
tests/e2e-playwright/ ├── config/ # 环境配置(app/env/databases) ├── fixtures/ # 测试夹具(页面对象、API 助手) ├── helpers/ # 工具函数(ApiHelper、retry 等) ├── pages/ # Page Object Models(组件化) │ └── databases/ │ ├── DatabasesPage.ts │ └── components/ │ ├── AddDatabaseDialog.ts │ └── DatabaseList.ts ├── test-data/ # 测试数据工厂 ├── tests/ # 测试文件,按项目组织 │ ├── main/ # 主并行测试(默认) │ │ ├── browser/ │ │ ├── workbench/ │ │ └── databases/ │ ├── auto-update/ # 自动更新测试(串行、特殊环境) │ └── electron/ # Electron 专属测试 ├── types/ # TypeScript 类型定义 ├── setup/ # 各项目的全局 setup/teardown │ ├── browser.setup.ts │ ├── browser.teardown.ts │ ├── electron.setup.ts │ └── electron.teardown.ts └── playwright.config.tsPage Object 结构(组件化 POM)
页面对象采用**组件化(component-based)**设计以提升可维护性:
BasePage (abstract) ├── DatabasesPage # 数据库列表页 ├── SettingsPage # 设置页 └── InstancePage (abstract) # 所有数据库实例页的基类 ├── instanceHeader # 数据库名、统计、面包屑 ├── navigationTabs # Browse / Workbench / Analyze / Pub/Sub ├── bottomPanel # CLI / Command Helper / Profiler └── BrowserPage # Browser 专属(继承 InstancePage) └── WorkbenchPage (future) └── AnalyzePage (future) └── PubSubPage (future)- BasePage:所有页面共用的导航方法;
- InstancePage:已连接数据库内部页面的基类,提供共享的 header、页签与底部面板;
- 组件级 POM(
AddDatabaseDialog、KeyList等):可复用的 UI 组件,通过页面对象暴露:
await databasesPage.addDatabaseDialog.fillForm(config); await browserPage.keyList.selectKey(keyName); // InstancePage 提供通用组件 await browserPage.instanceHeader.getDatabaseName(); await browserPage.navigationTabs.gotoWorkbench(); await browserPage.bottomPanel.openCli();测试组织:并行项目与串行项目
测试按执行要求(而非功能)先分成项目(文件夹),再按功能细分:
tests/ ├── parallel/ # 默认 —— 可多 worker 安全并行 │ ├── browser/ │ │ ├── add-key/ │ │ └── key-details/ │ ├── databases/ │ │ ├── add-database/ │ │ └── edit-database/ │ └── workbench/ └── serial/ # 必须顺序执行(共享 DB 状态、 │ # 危险命令、向量索引操作等) ├── cli/ ├── vector-search/ └── workbench/Playwright Projects(项目定义)
测试所在文件夹决定了它的执行模式。每个浏览器平台都有一对「并行 + 串行」项目(定义见 playwright.config.ts):
| 项目 | 文件夹 | 并行度 | 用途 |
|---|---|---|---|
chromium-parallel | tests/parallel/ | 并行(4 workers) | Chromium 浏览器标准测试 |
chromium-serial | tests/serial/ | 串行(1 worker) | Chromium 浏览器顺序测试 |
electron-parallel | tests/parallel/ | 串行(1 worker)* | Electron 桌面应用标准测试 |
electron-serial | tests/serial/ | 串行(1 worker)* | Electron 桌面应用顺序测试 |
* Electron 当前单 worker 运行,因为只有一个应用实例。
此外配置中还包含browser-setup/browser-teardown/electron-setup/electron-teardown四个生命周期项目,通过dependencies与teardown字段挂接到各测试项目上。全局use配置启用了trace: 'retain-on-failure'、screenshot: 'only-on-failure'、video: 'retain-on-failure',并设置 1920×1080 视口与expect.timeout = 10000;CI 环境下retries: 2、maxFailures: 20,本地retries: 1。
执行顺序与设计原因
每个平台中,serial 项目依赖 parallel 项目(dependencies: ['<platform>-parallel']),因此执行顺序恒为:
<platform>-parallel先跑(最多 N 个 worker)<platform>-serial后跑(单 worker 逐个执行)
为何串行而非并发?README 给出了三个明确理由:
- 串行测试会对共享 RTE Redis 执行破坏性操作(
FLUSHDB、宽泛的deleteAllIndexes、危险命令)。若与并行测试同时运行,并行测试可能在自身步骤之间观察到已被清空/擦除的数据库; - Electron 无法并发运行两个项目:桌面应用把内嵌 API 绑定在固定端口(
5530),两个应用实例会冲突。这也印证了 config/app.ts 中electronApiUrl固定指向http://localhost:5530的设计; - 保持心智模型简单:Chromium 与 Electron 采用同一执行模型——文件夹位置直接映射到运行顺序。
README 还给出前瞻性建议:若串行套件膨胀到让该顺序成为 CI 瓶颈,正确方向是给串行测试分配专属 Redis 实例(或拆成独立 CI 任务),而不是回退并发。
运行指定项目:
# 完整平台运行(parallel + serial) npx playwright test --project=chromium-parallel --project=chromium-serial npx playwright test --project=electron-parallel --project=electron-serial # 只跑 parallel npx playwright test --project=chromium-parallel # 只跑 serial —— 必须加 --no-deps,否则会先触发其依赖的 parallel 项目; # --no-deps 同时跳过 browser-setup,所以本地需确保应用已在运行 npx playwright test --project=chromium-serial --no-deps npx playwright test # 全部项目何时该把测试放进tests/serial/:
- 测试通过
beforeAll共享数据库状态,与其他 worker 并发会竞态; - 测试执行危险命令或修改全局应用状态;
- 测试覆盖天然串行的流程(如环境开关、单资源索引操作)。
编写测试:规范与示例
测试按功能区域组织,每个测试文件应遵循:
- 使用描述性的测试名称;
- 遵循AAA 模式(Arrange 准备 / Act 执行 / Assert 断言);
- 使用Page Object Model进行 UI 交互;
- 使用faker生成测试数据;
- 使用
test-data/中的测试数据工厂; - 在
afterEach中通过API清理创建的数据(更快更可靠)。
典型示例(来自 README):
import { test, expect } from '../../../fixtures/base'; import { getStandaloneConfig } from '../../../test-data/databases'; test.describe('Add Database > Standalone', () => { test.afterEach(async ({ apiHelper }) => { // 通过 API 清理所有测试数据库(快速) await apiHelper.deleteTestDatabases(); }); test('should add standalone database', async ({ databasesPage }) => { const config = getStandaloneConfig(); await databasesPage.goto(); await databasesPage.addDatabase(config); await expect(databasesPage.databaseList.getRow(config.name)).toBeVisible(); }); });注意测试从../../../fixtures/base导入test——这正是自定义 fixture 体系的入口(见下文),而不是 Playwright 默认的@playwright/test。
测试数据工厂
test-data/databases/index.ts 使用fishery的Factory.define声明式定义各类型连接配置,例如:
export const TEST_DB_PREFIX = 'test-'; export const StandaloneConfigFactory = Factory.define<AddDatabaseConfig>(() => ({ host: redisConfig.standalone.host, port: redisConfig.standalone.port, name: `${TEST_DB_PREFIX}standalone-${faker.string.alphanumeric(8)}`, }));关键设计:所有测试数据库名必须以test-前缀开头(TEST_DB_PREFIX),这是清理逻辑识别测试数据库的依据——browser.setup.ts中会调用apiHelper.deleteTestDatabases()删除上一轮遗留数据,保证每次运行从干净状态开始。faker.string.alphanumeric(8)生成的随机后缀用于避免并行运行时不同 worker 间的命名冲突。
API Helper:快速搭建与清理
apiHelperfixture 用于通过 API 完成测试的搭建/清理(比 UI 操作快得多)。其核心实现在 tests/e2e-playwright/helpers/api.ts:
test('should work with pre-created database', async ({ databasesPage, apiHelper }) => { // 通过 API 创建数据库(快速) const db = await apiHelper.createDatabase(getStandaloneConfig()); // 测试 UI 行为 await databasesPage.goto(); await expect(databasesPage.getDatabaseRow(db.name)).toBeVisible(); // 通过 API 清理 await apiHelper.deleteDatabase(db.id); });源码中值得注意的实现细节:
createDatabase内置了最多 4 次、指数退避(2s 起)的重试(retry工具,见 helpers/retry.ts):因为创建数据库时应用会先对目标建立 Redis 连接做校验,瞬时连接故障会整体失败,且应用把这类故障报告为404 Cannot POST /api/databases,与真正的路由缺失无法区分,因此不能依赖状态码决定是否重试;同时为避免「服务端已创建成功但客户端读响应失败」导致的重试重复建库,第二次尝试起会先按「名称 + host + port」匹配采纳已有库(因为重名是被允许的);- 请求上下文设置了
ignoreHTTPSErrors: true(Electron 测试使用自签名证书)以及 Electron 场景下携带X-Window-Id头用于 API 鉴权。
深入底层:fixture 体系与 setup/teardown
自定义 fixture(fixtures/base.ts)
fixtures/base.ts 通过base.extend<Fixtures, WorkerFixtures>扩展出整套测试基础设施,这是整套框架的枢纽:
apiHelper:API 助手(含 EULA 自动接受与销毁);featureFlags:功能开关覆盖,通过路由拦截GET /api/features注入指定标志状态,例如test.use({ featureFlags: { vectorSearchV2: true } })即可在测试中启用某功能开关——对应TEST_PLAN.md中 Vector Set 测试需开启dev-vectorSet标志的用法;electronApp(worker 级):当electronExecutablePath被设置时启动 Electron 应用,处理 splash 首屏等待、窗口windowId提取(X-Window-Id鉴权来源)、API 就绪轮询等;page:根据模式从浏览器或 Electron 应用获取页面,并统一执行「跳过 onboarding」(通过localStorage.setItem('onboardingStep', 'null'),比等待 UI 更快)与功能开关路由拦截;- 一批页面对象 fixture(
browserPage、databasesPage、cliPanel、profilerPanel、vectorSearchPage、typeToConfirmModal等),按需实例化。
全局 setup / teardown
以 setup/browser.setup.ts 为例,它在测试前完成两件事:
- 健康检查:分别请求
RI_CLIENT_URL(GET /)与 API(getDatabases()),任一失败立即报错并提示「请确认 RedisInsight 已运行在对应地址」,避免在应用未启动时盲目跑完全套测试; - 遗留数据清理:删除上一轮残留的
test-前缀数据库,打印清理数量。
对应地,browser.teardown.ts/electron.setup.ts/electron.teardown.ts负责各自的收尾与准备,全部通过 Playwright 的dependencies/teardown机制挂载,自动在测试前后执行。
从零开始跑通第一轮测试(实操清单)
综合以上内容,一份可直接照做的步骤清单:
- 拉起测试环境:
cd tests/e2e && docker-compose -f rte.docker-compose.yml up -d; - 配置 hosts(本地首次):按上文追加两行并
grep验证; - 启动应用:
- Chromium:仓库根目录分别跑
npm run dev:api与npm run dev:ui; - Electron:仓库根目录
npm run package:prod,并按平台设置ELECTRON_EXECUTABLE_PATH;
- Chromium:仓库根目录分别跑
- 安装测试依赖:
cd tests/e2e-playwright && npm install && npx playwright install chromium; - 配置环境:
cp example.env .env,按需调整连接信息; - 运行:
npm run test:chromium(浏览器)或npm run test:electron(桌面);调试用test:chromium:debug/test:chromium:ui,单项目运行记得处理--no-deps与项目依赖关系; - 查看报告:
npm run test:report打开 HTML 报告,结合 trace/video/screenshot 定位失败。
小结
RedisInsight 的 E2E 测试套件是一个「单套代码、双端复用」的成熟实践:以组件化 POM 抽象 UI、以项目分层隔离并行/串行风险、以自定义 fixture 打通 API 与 Electron 鉴权、以ENV多环境配置适配本地/CI/Staging。理解它的目录约定(tests/parallel/vstests/serial/)、执行顺序约束与 API 优先的搭建/清理策略,你就能稳定地为 RedisInsight 的任意功能模块贡献高质量 E2E 测试。若需深入,可继续研读 tests/e2e-playwright/TEST_PLAN.md 的覆盖矩阵,以及 .ai/skills/e2e-testing/SKILL.md 的编码标准。
【免费下载链接】RedisInsightRedis GUI by Redis项目地址: https://gitcode.com/GitHub_Trending/re/RedisInsight
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考