后端前端即时通讯社交【免费下载链接】spectrumSimple, powerful online communities.项目地址https://gitcode.com/gh_mirrors/sp/spectrum点击查看免费下载Spectrum 的集成测试Integration Tests用于在真实浏览器环境中验证「API 前端客户端」协同工作的完整链路确保社区、频道、帖子、消息等核心功能持续可用。本文基于 docs/testing/integration.md 展开结合 package.json、cypress.json 以及 cypress/ 目录下的真实测试代码完整讲解环境搭建、测试编写、data-cy选择器约定与测试数据库机制帮助你直接上手为 Spectrum 编写可运行的端到端测试。集成测试在 Spectrum 测试体系中的定位Spectrum 的测试体系由两部分构成参见 docs/testing/intro.md单元测试Unit tests主要集中在api/下使用 Jest 验证 API 层的模型、工具函数与解析器逻辑集成测试Integration tests使用 Cypress 驱动真实浏览器从页面层验证「客户端渲染 GraphQL API 数据库」整条链路是否按预期工作。整个测试套件会在每次提交commit和每个 PR 的 CI 中运行一旦有破坏性改动导致 CI 失败该 PR 将无法合并。集成测试正是守住前端交互与 API 契约的最后一道防线。从 package.json 的脚本可以看出仓库为集成测试准备了完整的命令链build:api、start:api:test、dev:web、cypress:open以及用于 CI 的无头模式脚本test:e2e。这些脚本的用途会在下文逐一展开。前置环境以生产模式 API 测试数据库 前端客户端搭建运行环境与单元测试不同集成测试需要整套服务真实运行。文档明确说明API 必须以生产模式production mode构建运行并连接到测试数据库同时前端客户端web client也必须在本地启动。之所以要求生产模式是因为生产构建build-api更接近线上行为避免开发模式下热更新、调试日志等带来的不确定性。第一步构建 APIyarn run build:api该命令实际执行的是 package.json 中的prebuild:api: rimraf build-api, build:api: cross-env NODE_PATH./ cross-env DIRapi backpack build, postbuild:api: cp api/package.json build-api/package.json cp now.json build-api/now.json cpy cacert build-api即先清空旧的build-api/目录再用 backpack 以DIRapi为入口构建 API构建完成后把api/package.json、now.json与cacert一并拷贝进产物目录保证build-api/main.js可独立运行。第二步在第一个终端启动测试模式的 APIyarn run start:api:test对应脚本为 package.jsonprestart:api:test: node -e \require(./shared/testing/setup.js)().then(() process.exit())\, start:api:test: TEST_DBtrue FORCE_DEVtrue DEBUGapi*,shared* forever build-api/main.js这里有两个值得注意的细节prestart:api:test钩子在 API 启动前自动执行 shared/testing/setup.js完成测试数据库的迁移与种子数据写入详见下文「测试数据库机制」一节因此你无需手动初始化数据库环境变量组合TEST_DBtrue让 API 连接测试数据库库名为testingFORCE_DEVtrue强制以开发辅助模式运行用于测试场景同时通过DEBUGapi*,shared*打开 API 与 shared 层的调试日志方便排查问题。进程由forever托管保证 API 在集成测试期间持续存活。第三步在另一个终端启动 Web 客户端yarn run dev:web对应脚本为 package.jsondev:web: cross-env NODE_PATH./ react-app-rewired start即通过react-app-rewired启动基于 config-overrides.js 定制的 React 开发服务器。Cypress 配置的baseUrl是http://localhost:3000见 cypress.json因此该客户端默认端口为 3000与集成测试的访问地址保持一致。第四步打开 Cypress 图形界面yarn run cypress:open对应脚本 package.json 为cypress open。它会弹出 Cypress 的 GUI 运行器runner你可以看到所有位于cypress/integration/下的测试文件并逐个点击运行。对于需要调试断言、观察页面状态变化的场景GUI 模式下可以实时看到每一步命令在浏览器中的执行过程这也是文档强调 Cypress「给你一个很棒的 GUI」的原因。无头模式面向 CI 的运行方式如果不需要 GUI例如在 CI 中仓库还提供了无头运行脚本test:e2e: CYPRESS_RETRIES2 cypress runCYPRESS_RETRIES2配合依赖 cypress-plugin-retries在 cypress/support/index.js 中通过require(cypress-plugin-retries)加载允许失败的测试自动重试至多 2 次有效缓解端到端测试中常见的偶发性失败如网络抖动、动画时序。cypress run会以无头模式依次执行全部测试文件并输出汇总结果。测试数据库机制迁移 种子数据 自动复位集成测试依赖一个独立且可预测的测试数据库库名testing相关实现集中在 shared/testing/ 目录。shared/testing/setup.js 在每次运行前负责两件事执行全部数据库迁移通过rethinkdb-migrate将 api/migrations/ 下的所有迁移脚本按顺序应用到testing库写入种子数据从 shared/testing/data.js 读取预置数据用户、社区、频道、帖子、消息、成员关系等按表插入并使用{ conflict: replace }保证数据可重复覆盖。而 shared/testing/teardown.js 负责清空testing库中各表的数据。值得一提的是文件头部的注释说明之所以不直接用dbDrop(testing)删库是因为删库会导致 RethinkDB 的 changefeed 断连、正在运行的 API 崩溃因此只清数据、保留库结构。在测试执行层面cypress/support/index.js 在每个测试文件的before以及每个用例的beforeEach中都调用cy.resetdb()同时清空 localStorage 与 cookies确保每个用例都从干净、确定的数据库状态开始杜绝用例之间的数据串扰。cy.resetdb()在 cypress/support/commands.js 中定义本质是依次执行 teardown 与 setup 两个 Node 脚本。编写集成测试目录结构、异步队列与断言写法测试文件放哪里所有集成测试文件都位于cypress/integration/目录下。从仓库现状看测试已按业务模块组织了子目录cypress/integration/channel/频道设置删除、编辑与频道视图成员、资料、帖子列表cypress/integration/community/社区视图资料页cypress/integration/thread/帖子操作栏与帖子视图cypress/integration/user/用户删除、资料编辑、登录重定向以及顶层的一批功能测试login_spec.js、thread_spec.js、messages_spec.js、explore_spec.js、toasts_spec.js、modal_routes_spec.js、community_settings_members_spec.js、community_settings_overview_spec.js、user_spec.js。一个最基本的测试文档给出的最简示例首页渲染测试// cypress/integration/home_spec.js describe(Home View, () { before(() { cy.visit(/); }); it(should render the home page, () { cy.get([data-cyhome-page]).should(be.visible); cy.get([href*/login]).should(be.visible); }); });仓库中与之对应的真实案例是 cypress/integration/login_spec.jsdescribe(Log in, () { beforeEach(() { cy.visit(/login); }); it(should render login methods, () { cy.get([data-cylogin-page]).should(be.visible); cy.get([href*/auth/twitter]).should(be.visible); cy.get([href*/auth/facebook]).should(be.visible); cy.get([href*/auth/google]).should(be.visible); cy.get([href*/auth/github]).should(be.visible); }); });理解 Cypress 的异步队列模型文档特别提醒Cypress 的 API 表面看起来是同步的底层其实是完全异步的。每个cy.*命令如cy.visit、cy.get、cy.contains只是把一条命令追加进内部队列Cypress 会按顺序依次执行并自动等待上一条命令的结果满足条件后才继续下一条。因此你不能像写普通同步 JS 那样在命令之间直接使用返回值除非通过.then()也不能在cy.visit之后立即用同步代码断言页面状态——一切都交给队列机制去编排等待。刚开始可能会觉得有点绕但熟悉之后会发现它天然解决了「等待元素出现」「等待请求完成」这类时序问题。Cypress 还内置了默认超时仓库在 cypress.json 中把defaultCommandTimeout设为2000020 秒意味着单个命令默认最多等待 20 秒元素一直不满足条件才会失败比 Cypress 默认的 4 秒更宽容适合数据量较大、渲染较慢的页面。Mocha 语法与 Jest 断言风格的差异Cypress 底层使用 Mocha 作为测试框架而 Spectrum 的单元测试使用 Jest。这两者的expect实现不同语法也有差异单元测试Jestexpect(value).toEqual(expected)集成测试Mocha/Chaiexpect(value).to.equal(expected)。从 cypress/integration/thread_spec.js 可以看到真实的 Chai 断言用法cy.get([data-cymessage-selected]).should($p { expect($p).to.have.length(1); }); cy.get([data-cymessage]).should($p { expect($p).to.have.length(3); });即to.have.length(n)这类 Chai 链式断言。写作时需要注意这套语法差异避免把 Jest 的写法直接搬进 Cypress 用例。Test IDs用data-cy属性建立稳定的元素定位约定为了保证测试选择器不受样式类名、组件结构重构的影响Spectrum 约定在 React 组件上挂载自定义的data-cy属性。文档给出的示例class HomePage extends Component { render() { return ( Wrapper>// cypress/integration/home_spec.js it(should render, () { cy.get([data-cyhome-page]).should(be.visible); });这一约定在源码中广泛落地例如src/views/login/index.js 挂载data-cylogin-pagesrc/views/thread/container/index.js 挂载data-cythread-viewsrc/components/messageGroup/thread.js 与 src/components/messageGroup/directMessage.js 挂载data-cymessage-groupsrc/components/message/index.js 挂载data-cydelete-message。这些正是 cypress/integration/thread_spec.js 中断言所依赖的选择器。采用data-cy而非 CSS class 或 id意味着即使样式系统styled-components生成的类名发生变化只要组件语义不变测试就不会被破坏——这也是 Cypress 官方 Best Practices 强烈推荐的做法文档建议在动手编写测试前先通读 Cypress 官方文档的 Best Practices 章节。真实用例拆解以thread_spec.js为例的进阶模式cypress/integration/thread_spec.js 是一个信息量很大的真实测试文件覆盖了多个进阶模式1. 从测试种子数据中取用业务对象测试直接导入shared/testing/data与api/migrations/seed/default/constants从种子数据中按 id 关联出帖子、社区、作者、版主、消息列表再拼装出访问 URL 与预期断言import { toPlainText, toState } from ../../shared/draft-utils; import data from ../../shared/testing/data; import { SPECTRUM_PRIVATE_CHANNEL_ID, QUIET_USER_ID, } from ../../api/migrations/seed/default/constants; const thread data.threads[0]; const community data.communities.find( community community.id thread.communityId );2. 权限场景的差异化断言同一页面在「匿名用户」「帖子作者」「社区版主」「无权用户」四种身份下行为不同。例如帖子作者只能删除自己的消息delete-message元素仅 1 个社区版主可以删除全部消息delete-message元素有 4 个无权用户访问私密帖子时看到的是data-cynull-thread-view。3. 消息内容断言通过shared/draft-utils的toPlainText/toState把 DraftJS 的 JSON 内容解析为纯文本再与页面文本比对cy.contains(toPlainText(toState(JSON.parse(thread.content.body))).split( )[0]);4. 带查询参数的路由测试访问/thread/thread-1?mMTQ4MzIyNTIwMDAwMQ验证「定位到某条消息」的深链接行为断言选中的消息数量与普通消息数量。自定义命令认证、数据库复位与 DraftJS 输入cypress/support/commands.js 定义了三个支撑整套测试的关键能力cy.auth(userId)注入会话 Cookie 模拟登录Cypress.Commands.add(auth, userId { const user getUser(userId); return cy.setCookie( session, encode(JSON.stringify({ passport: { user: user.id } })), { httpOnly: true, secure: false } ); });它从种子数据中取出指定用户把{ passport: { user: userId } }用 api/utils/base64.js 的encode编码后写入sessionCookie。这样测试无需走完整的 OAuth 登录流程即可模拟任意用户普通用户、帖子作者、社区版主的登录态。用法示例见 cypress/integration/thread_spec.jscy.auth(author.id).then(() cy.visit(/thread/${thread.id}));cy.resetdb()重置数据库到种子状态Cypress.Commands.add(resetdb, () { cy.exec(node -e const teardown require(./shared/testing/teardown.js)().then(() process.exit())); cy.exec(node -e const setup require(./shared/testing/setup.js)().then(() process.exit())); });在 cypress/support/index.js 中该命令会在每个测试文件开始前与每个用例前被调用配合cy.clearLocalStorage()与cy.clearCookies()保证用例隔离。重写type支持 DraftJS 富文本编辑器Cypress.Commands.overwrite(type, (originalFn, $elem, text, options) { const textarea $elem[0]; if (textarea.attributes.contenteditable) { var textEvent document.createEvent(TextEvent); textEvent.initTextEvent(textInput, true, true, null, text); textarea.dispatchEvent(textEvent); return Promise.resolve($elem); } else { return originalFn($elem, text, options); } });Spectrum 的消息与帖子编辑使用 DraftJS其编辑器根节点是contenteditable元素原生cy.type对其并不友好。这个覆盖实现会在目标是 contenteditable 元素时派发TextEvent模拟输入否则回退到原生type。这是「测试框架适配业务特性」的典型例子。Cypress 配置速览cypress.json 中与集成测试直接相关的配置如下配置项值说明baseUrlhttp://localhost:3000所有cy.visit(/...)的相对路径都基于此解析对应dev:web的客户端端口viewportWidth1300测试视口宽度保证桌面布局下断言元素可见defaultCommandTimeout20000单条命令默认等待上限 20 秒env.DEBUGsrc*,testing*,build*向测试注入的调试命名空间projectId6a92ukCypress Dashboard 项目标识结合 cypress/plugins/index.jsCypress 插件入口与 cypress/fixtures/example.jsonfixture 示例可以看出整套 Cypress 工程结构是完整且可扩展的。常见问题与调试建议用例之间数据互相污染请确认每个用例的beforeEach都执行了cy.resetdb()Spectrum 在 cypress/support/index.js 已全局配置新写的测试无需重复添加。元素断言不稳定优先使用data-cy选择器保持与源码约定一致并充分利用cy.contains按可见文本定位对需要等待的异步渲染20 秒的默认超时一般足够避免盲目cy.wait(固定毫秒)。偶发失败CI 场景下可借助yarn run test:e2e自带的CYPRESS_RETRIES2重试机制先排除时序类抖动若重试后仍稳定失败则说明是真实回归。区分断言语法集成测试用的是 Chaito.equal、to.have.length不要与 Jest 的toEqual、toHaveLength混用。本地运行顺序务必先yarn run build:api再yarn run start:api:test否则 API 产物缺失或版本陈旧会导致测试行为与预期不符start:api:test的prestart钩子会自动完成测试库的迁移与种子数据初始化。通过以上流程你就可以在本地完整跑起 Spectrum 的集成测试并依据data-cy约定、cy.auth认证注入与测试数据库机制为新的页面功能编写稳定、可维护的端到端用例。相关源码均可在 cypress/、shared/testing/ 与 api/migrations/seed/ 中查阅。赞分享后端前端即时通讯社交【免费下载链接】spectrumSimple, powerful online communities.项目地址https://gitcode.com/gh_mirrors/sp/spectrum点击查看免费下载相关推荐spin.js中的端到端测试Cypress集成实践spin.js中的端到端测试Cypress集成实践 为什么需要端到端测试Spinner组件 在现代Web应用中加载状态指示器Spinner是提升用户体验UI组件前端Metabase 端到端测试实践指南基于 Cypress 的 E2E 测试体系全解析Metabase 端到端测试实践指南基于 Cypress 的 E2E 测试体系全解析 Metabase 使用 Cypress 构建了一套完整的端到端E2E数据分析数据可视化后端数据库客户端企业应用runc 集成测试指南基于 bats 的端到端测试架构与实践runc 集成测试指南基于 bats 的端到端测试架构与实践 runc 的集成测试位于 tests/integration/README.md https:/容器运行时云原生创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
Akka Streams `Source.range` 操作符完全指南:生成整数序列、步长控制与底层实现原理 后端并发编程异步编程 【免费下载链接】akka-core A platform to build and run apps that are elastic, agile, and resilient. SDK, libraries, and hosted environments. 项目地址: https://gitcode.com/gh_mirrors/ak/akka-core 点击查看 免费下载 Source.rang… · 2026/9/23 21:46:44
拟牛顿算法SR1、DFP、BFGS公式推导与Python实现 1. 为什么拟牛顿算法值得你花时间搞懂如果你做过一点数值优化或者机器学习模型的训练,大概率听过“牛顿法”这三个字。牛顿法本身很优雅,用二阶导数信息(Hessian矩阵)来指导迭代方向,收敛速度是二次的,理论… · 2026/9/23 21:46:31
R语言GAM时间序列预测:加法与乘法结构选择及避坑指南 简介:这份资源面向具备一定R语言基础、希望深入掌握时间序列建模的数据分析与预测从业者,聚焦加法与乘法过程两类核心思路,并延伸至广义可加模型(GAM)的非线性建模场景。压缩包内共1个文件,为R脚本… · 2026/9/23 21:46:31
EN1175-2020工业卡车电气安全设计核心解析 简介:本资源为欧洲标准EN 1175:2020《工业卡车的安全——电气/电子要求》中文版全文PDF,面向工业车辆制造商、安全工程师、设备检测机构及特种作业合规管理人员,解决工业搬运车辆在电气设计、控制接口、能量连接、EMC防护及维护验证等环节的安… · 2026/9/23 22:18:11
人肉评审vs AI评审:modern-software-dev-assignments一周体验对比 人肉评审vs AI评审:modern-software-dev-assignments一周体验对比 【免费下载链接】modern-software-dev-assignments Assignments for CS146S: The Modern Software Dev (Stanford University Fall 2026/2025) 项目地址: https://gitcode.com/GitHub_Trending/mo… · 2026/9/23 22:18:05
企业CMMI认定可以解决企业存在的哪些问题 我们知道CMMI认定的作用是非常大的,因此很多企业如今都是费尽各种心思想要通过CMMI认定,其实企业通过CMMI认定不仅能够给他们带来诸多的好处,还能解决它们的很多问题,具体的有哪些问题呢?让我们一起来看一下。
1、企业不能集中的… · 2026/9/23 22:18:05
SAP工单拆解机制:CO07、MIGO与成本归集协同原理 简介:本资源是面向SAP PP模块实施顾问与生产计划人员的深度实践指南,系统解析SAP中拆解工单这一特殊生产订单类型的全流程设计与落地要点。内容覆盖拆解业务场景(如故障电脑部件回收)、财务结算逻辑(成本不计入产品、归… · 2026/9/23 22:17:58
BCH纠错码原理与C/C#实现:从GF域表到NAND Flash实战 简介:C#实现的BCH(Bose-Chaudhuri-Hocquenghem)编码解码源代码,面向通信、存储等领域需要数据纠错功能的开发者,也适合编码理论初学者结合算法验证。代码针对m≤20场景做了修正,能稳定处理较短码字长度&… · 2026/9/23 22:17:25
14岁少年四年造机械臂:Rust重写驱动与3D打印避坑指南 1. 一个14岁少年的四年硬核长跑,到底在折腾什么先把这件事的轮廓说清楚。一个14岁的少年,花了整整四年时间,从零开始做了一台机械臂。中间经历过3D打印件反复开裂、结构推倒重来、电路板画了又废,最后用Rust重写了底层驱动&#x… · 2026/9/23 22:17:25
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29