使用 Cypress 测试使用 Canvas、D3.js 和 React 构建的基因组图
最初发布于nunocruz.pt 与任何其他 Feedzai 产品一样,Genome 需要经过全面的端到端 (E2E) 测试,以确保其按照设计规范工作。由于基因组是一种高度可视化的工具,因此测试需要一种非常特殊的方法。我们使用 HTML 画布元素构建图形区域,这使我们无法使用传统的 E2E 技术。在这篇博文中,我们将解释我们如何处理和解决测试主要交互发生在画布元素上的应用程序的问题。 测试白板 使
最初发布于nunocruz.pt
与任何其他 Feedzai 产品一样,Genome 需要经过全面的端到端 (E2E) 测试,以确保其按照设计规范工作。由于基因组是一种高度可视化的工具,因此测试需要一种非常特殊的方法。我们使用 HTML 画布元素构建图形区域,这使我们无法使用传统的 E2E 技术。在这篇博文中,我们将解释我们如何处理和解决测试主要交互发生在画布元素上的应用程序的问题。
测试白板
使用当前的 E2E 框架(如 Selenium 或 Cypress)测试传统的 Web 应用程序(“传统”是指用户界面 (UI),其中每条信息都使用 HTML 元素显示)或多或少是简单的。总体而言,工作流包括在页面上执行一组操作,例如单击按钮或在输入元素上键入文本并断言页面进入所需状态(例如,断言页面上存在某些元素)。
这适用于几乎所有 HTML 元素,除了 canvas 元素。如果您不熟悉 canvas,它是一个 HTML 元素,可用于通过脚本绘制图形。我们可以把它想象成一块白板,你可以在上面自由地画任何东西。
与我们可以将多个元素相互嵌套(DOM 树)以生成内容的其他 HTML 元素相比,我们在 canvas 元素上看到的内容不会在任何嵌套元素中表示,这意味着它不会生成可查询的 DOM 树。从测试的角度来看,如果我们无法查询画布元素的内容,我们如何断言我们的应用程序进入了所需的状态?例如,我们如何测试从图中删除一个节点后,我们得到 n - 1 个节点?
公开 API
在解释我们如何为 Genome 实施 E2E 测试之前,重要的是要提供一些关于 Genome,特别是它的图是如何构建的背景信息。
Genome 的图是使用 React 和 D3.js 的组合构建的。一个名为 GenomeGraph 的 React 组件嵌入了 canvas 元素。总体而言,该组件负责设置和处理以图为目标的用户事件。它还与 D3.js 通信以计算节点和边的位置。
D3.js 是一个著名的库,用于帮助构建可视化工具。对于 Genome,默认情况下,我们使用 D3.js 强制导向图布局。此布局模拟节点上的物理力,直到它们平衡(它们的最终位置)。从视觉上讲,模拟越多,节点越倾向于彼此分离,而更少的模拟可能会使它们彼此靠近。图 1 说明了模拟数量大于图 2 中的模拟数量的场景。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--IcfISdpB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://nunocruz.pt/ static/0a2ab3fce25a25e23b00df4679777ea1/7d769/graph-300-iterations.png)_图 1. 大约 300 次迭代的 D3.js 力模拟。正如所解释的,在这种情况下,与图 2 中的图表相比,节点彼此之间略微分开。
[](https://res.cloudinary.com/practicaldev/image/fetch/s--ZcwRzWAz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://nunocruz.pt/ static/508c9eeb7cbe4e9c9879d02d33c70153/7d769/graph-13-iterations.png)图 2. 大约 13 次迭代的 D3.js 力模拟。
Cypress over Selenium
我们决定使用赛普拉斯来实施我们的 E2E 测试。为什么选择 Cypress 而不是 Selenium? Cypress 更加以开发人员为中心,因为任何前端开发人员都可以使用 JavaScript 轻松实现 E2E 测试。另一个优点是 Selenium WebDriver 在浏览器之外远程运行,Cypress 正好相反;它在浏览器中运行。在浏览器中运行代码的能力简化了事情。例如,您可以简单地将调试器放入您的应用程序或规范代码中 - 这使得在开发时使用开发人员工具变得超级容易。除了技术方面,当我们做出决定时,Cypress 在前端社区中获得了很大的关注。考虑到所有这些,我们决定试一试赛普拉斯(到目前为止没有遗憾)。
现在我们对用于实现和测试基因组图的工具有了更多的了解,是时候详细说明我们如何能够测试在画布元素中绘制的图了。
如何测试在画布元素中绘制的图形
经过一些分析,我们决定使用 API 来公开基因组应用程序以供赛普拉斯应用程序使用。这使我们能够操纵图形并断言其状态。由于 GenomeGraph 组件的特性,我们使用它来帮助构建 API 是一个“自然”的选择。
高阶组件 (HOC) 是 React 中用于重用组件逻辑的高级技术。我们使用这种技术是因为它从给定组件生成增强组件。特别是,我们从 GenomeGraph 组件生成了一个增强组件,该组件能够创建 API 并将其公开在浏览器的全局对象中。尽管它不可重用,但这种方法似乎是公开组件 API 的最简洁、最优雅的方式。
由于我们不希望在生产环境中公开此 API,因此我们定义了一个变量以仅在测试环境中启用它。
在 API 公开的一组操作中,最有用的是 waitUntilGraphSimulationEnd 操作。它允许我们等待 D3.js 模拟完成,以便开始与图形交互。没有它,与图交互将非常困难,并且可能导致不稳定的测试,因为图仍在从其初始状态“移动”到其最终状态。
下面的代码片段描述了等待模拟结束的函数的实现。
实现自定义命令
从赛普拉斯应用程序的角度来看,我们创建了几个自定义命令来抽象与基因组图的通信。下面的代码片段描述了 getGraphNodeInformationById 和 waitUntilGraphSimulationEnd 自定义命令的实现。
在实现我们的测试时,我们使用自定义命令,就好像它们是赛普拉斯库的一部分一样。下面的示例是一个测试,它断言当单击特定节点时,该节点被选中。您可以注意到前面提到的 waitUntilGraphSimulationEnd 和 getGraphNodeInformationById 自定义命令的用法。
最后的想法
采用基于赛普拉斯应用程序和基因组应用程序之间“直接通信”的方法,我们可以将我们的主要组件(基因组图)包含在 E2E 测试集中。但是,我们知道这种方法的缺点。
E2E 测试的目标之一是像用户一样与应用程序交互:单击屏幕,输入文本并期望在屏幕上看到变化。通过使用基于 API 的方法,我们以某种方式打破了这个目标。在实践中,我们通过直接从 Genome 应用程序调用代码来伪造与图的交互。
另一个限制是拖放操作。目前,我们无法测试将节点拖动到屏幕某些部分的场景,因为我们注意到它在我们的测试中引入了片状。虽然我们正在研究解决此限制的解决方案,但添加了一组手动测试来涵盖拖放操作。
可视化测试是功能测试的替代方法,是一种应该在不久的将来探索的方法。该技术获取应用程序的图像快照,并将它们与先前批准的基线图像进行比较。这是一种非常适合主要通过可视化对信息进行编码的特征的技术。例如,在 Genome 中,我们有一个名为 Lenses 的新功能,旨在将不同的颜色应用于节点和边缘以对某些信息进行编码,例如,参与的实体,至少一个欺诈交易显示为红色,而仅参与的实体真实交易显示为绿色。将图像快照与基线图像进行比较将是断言镜头正确应用于节点和边缘的一种有趣方式。
我们测试主要使用画布构建的应用程序的解决方案远非完美,我们的目标是不断迭代以解决当前的限制。
注意:此解决方案的功劳归于Liliana Fernandes和Victor Fernandes。我只是信使 :D
更多推荐
所有评论(0)