如何使用 Cypress 编写有效的端到端测试
AWS AI 直播!
测试已成为软件工程中不可或缺的一部分,这也不无道理。编写任何复杂程度的软件通常都是一项繁琐的工作,而当团队规模扩大、更多人参与同一代码库的开发时,情况只会更加糟糕。
这个问题在前端开发中尤为严重,因为前端涉及的组件众多,编写单元测试和功能测试可能不足以验证应用程序的正确性。例如,你无法通过单元测试来真正验证某个特定的用户流程是否会导致问题。
端到端测试允许您在应用程序中重现用户行为,并验证一切是否按预期运行。如果您正在编写生产级 Web 应用程序,那么编写端到端测试是必不可少的。
本文将介绍如何使用Cypress编写有效的前端端到端测试。虽然还有其他端到端测试工具,例如Selenium和Nightwatch.js,但我们将重点介绍 Cypress,因为它提供了一系列丰富的功能,包括测试时间回溯、录制测试以供后续回放等等。
注意:要学习本教程,您需要安装 Node.js。如果您还没有安装,可以从这里下载最新的稳定版本。
设置 Cypress
让我们创建一个新项目并设置 Cypress,以便开始。
运行以下命令初始化新项目:
mkdir cypress-tutorial
cd cypress-tutorial
npm init -y
将 Cypress 安装为开发依赖项:
npm install --save-dev cypress
请打开并更新项目脚本,package.json内容如下:
"scripts": {
"test": "$(npm bin)/cypress run",
"cypress:open": "$(npm bin)/cypress open"
},
在根文件夹下创建一个名为 `.cypress.yml` 的文件cypress.json。这将用于自定义 Cypress 在此特定项目中的行为。将以下内容添加到该文件中并保存。
{ "chromeWebSecurity": false }
我们这样做的原因将在下文中解释,请继续阅读。
编写我们的测试
用户故事(对于我们这些实践敏捷的人来说)通常遵循如下格式:“当用户执行特定操作时,用户应该看到此内容。”
分析这一点后,你就可以确定如何为这个特定用户故事编写端到端测试。你只需要在测试中模拟用户预期执行的操作,然后断言应用程序状态与预期相符即可。
对于前端测试,这些步骤通常可以分解为以下几个方面:
- 访问您应用上的一个页面
- 查询页面上的元素,例如按钮、下拉菜单等。
- 与元素进行交互,例如点击按钮、拖动div元素等。
- 确认交互后的新状态是否正确
我们将编写三个测试用例,以验证我们能否通过模拟用户操作在维基百科上执行某些操作。对于每个测试用例,我们都会在编写实际测试用例之前先编写一个用户故事。
在开始编写测试之前,您需要创建一个专门的文件夹来存放 Cypress 测试。在项目根目录下,运行以下命令:
mkdir cypress && cd cypress
mkdir integration && cd integration
所有的 Cypress 测试都将放在这个/integration文件夹里。不用担心文件夹名称,因为你可以把任何类型的测试都放在这里。
注意:请勿在您不拥有的网站/应用程序上使用 Cypress。Cypress 仅用于测试您自己的应用程序,而非用于自动化您的个人生活。
测试 1:用户可以从首页执行搜索
当用户访问主页,在搜索框中输入内容,然后点击搜索图标时,用户应该会看到一个新页面,其中填充了与其搜索词匹配的结果。
用户故事非常简单:它只是验证假设用户在首页执行搜索操作时的行为是否正确。让我们来编写测试。
在文件夹内/integration,创建一个名为 的新文件homepage_search_spec.js,并在你喜欢的文本编辑器中打开它(我使用的是 Visual Studio Code)。
describe('Testing Wikipedia', () => {
it('I can search for content', () => {
cy.visit('https://www.wikipedia.org');
cy.get("input[type='search']").type('Leo Panthera');
cy.get("button[type='submit']").click();
cy.contains('Search results');
cy.contains('Panthera leo leo');
});
});
让我们一起完成测试,看看它是否符合我们之前定义的步骤。
- 第 3 行:访问您应用上的一个页面
- 第 4 行:查询该页面上的一个元素并与之交互。
- 第 5 行:查询该页面上的一个元素并与之交互。
- 第 6 行:确认交互后的新状态是否正确
- 第 7 行:确认交互后的新状态是否正确
大多数端到端测试都会遵循上述格式,您很快就能体会到这种测试方式的优势。您无需关心应用程序在后台如何处理这些操作;您只需关注应用程序针对特定操作应如何执行即可。
语法怎么样?我喜欢 Cypress 的一点就是它直观的语法。它使用自然语言,即使是非程序员也能轻松阅读和理解你的测试代码。
让我们运行测试。在终端中运行命令,npm testCypress 将进入该cypress/integration文件夹并运行其中的所有测试。
但这并非运行测试的唯一方法。您还可以通过图形用户界面 (GUI) 运行测试,在 GUI 中,您可以实时查看 Cypress 如何根据您的测试规范对应用程序进行操作。
在终端中运行命令,npm run cypress:open应该会弹出一个类似这样的窗口:
只需点击homepage_search_spec.js运行测试,您应该会看到另一个窗口弹出。
窗口左上角可以快速查看测试套件中通过和失败的测试数量。窗口右侧显示的是用户按照您在测试中指定的方式与应用程序交互后会看到的内容。
左侧是大部分功能实现的地方。在这里,你可以看到当前正在运行的测试、正在执行的操作以及这些操作的结果。
通过这个简单的测试,我们已经能够断言,任何参与维基百科搜索功能开发的人员都能够满足假设的用户故事要求。
测试 2:用户可以从首页切换语言
当用户访问主页,点击语言切换器并选择一种新语言时,该用户应该被重定向到所选语言的相应域名。
在文件夹内/integration,创建一个名为“新文件”的文件homepage_switch_language_spec.js并打开它。
describe('Testing Wikipedia', () => {
it('A user can switch languages', () => {
cy.visit('https://wikipedia.org');
cy.contains('Read Wikipedia in your language');
cy.get('#js-lang-list-button').click();
cy.contains('Yorùbá').click();
cy.url().should(
'equal',
'https://yo.wikipedia.org/wiki/Oj%C3%BAew%C3%A9_%C3%80k%E1%BB%8D%CC%81k%E1%BB%8D%CC%81',
);
cy.contains('Ẹ kú àbọ̀');
});
});
现在我们来谈谈 Cypress 特有的语法。
第 3 行,我们只是访问维基百科的首页。第 4 行,我们通过确认页面包含“用你的语言阅读维基百科”这句话来断定我们位于想要访问的页面上。
在第 5 行,我们通过 id 查询语言切换按钮,并模拟点击操作。我知道这个 id 是因为我在 Chrome 的开发者工具中检查过它。这引出了 Cypress 测试编写中的一个重要概念:在 Cypress 中,选择 DOM 元素的方法有很多种。你可以通过 id、class 甚至 tag type 来选择元素。
在这个测试中,我们选择的是按钮的 id,但在之前的测试中,我们选择的是标签名称和属性。您可以点击此处了解选择 DOM 元素的不同方法。
在第 6 行,我们遇到了另一个常见的 Cypress 命令,你会注意到它在测试中经常出现。我们断言 DOM 中存在一个文本为“Yorùbá”的元素,然后模拟点击该元素。
此操作将使维基百科将您重定向到您所选语言的相应域名。在本例中,我们选择了西非的约鲁巴语,通过查看当前页面的 URL,我们可以确认已重定向到正确的页面。
第 7 行正是如此。通过调用函数,cy.url()我们获取当前页面的 URL 文本,然后断言它应该等于约鲁巴语对应的域名。第 8 行,我们添加了一个可选的额外检查,查看页面上是否存在约鲁巴语内容。
额外事实: Ẹ kú àbọ̀ 在约鲁巴语中意为“欢迎”,发音为:Eh – Koo – AhBuh。
按照与上次相同的方式运行测试,它应该会通过。
测试 3:用户可以在维基词典上查看单词的定义。
当用户访问主页并点击维基词典的链接时,该用户应该被重定向到 wiktionary.org。
当用户在 wiktionary.org 上通过搜索栏输入定义并按下回车键进行搜索时,该用户应该被重定向到一个包含该搜索词定义的页面。
另一个简单的用户故事。我们想在维基词典上查找“Svelte”(苗条的)这个词的定义,但我们会先从维基百科首页开始,然后导航到维基词典,最后再搜索这个词。
在文件夹内/integration,创建一个名为 `<filename>` 的新文件homepage_search_definition.js并打开它。
describe('Testing Wikipedia', () => {
it('A user can search for a word', () => {
cy.visit('https://wikipedia.org');
cy.get('.other-project-link')
.eq(2)
.click();
cy.url().should('equal', 'https://www.wiktionary.org/');
cy.get('#searchInput').type('Svelte{enter}');
cy.contains('Etymology');
cy.contains('svelte');
});
});
让我们用和上一个测试相同的方法来完成这个测试。
第 3 行,我们像往常一样访问维基百科首页。第 4 行,我们选择一个类名,选取具有该类名的第三个元素(请记住索引从 0 开始),并模拟点击该元素。
在继续之前,需要注意一点:如果你的代码依赖于自动生成的 CSS 类,那么通过类名来定位元素可能会导致测试结果不一致。在这种情况下,通过 id 或标签类型和属性来定位元素才是正确的做法。
在第 7 行,我们通过使用cy.url().
另一个注意事项:如果您正在测试自己的应用程序,则很少需要导航到另一个域,正因如此,如果我们不将此功能添加"chromeWebSecurity": false到cypress.json配置中,则此测试将会失败。
在第 8 行,我们通过 id 定位搜索输入框,然后通过输入“Svelte”并按下回车键来模拟一个更改事件(按下回车键的操作由“{enter}”处理)。此操作会将我们带到一个显示查询结果的新页面。
然后,我们在第 9 行和第 10 行确认我们是在正确的页面上,并断言“词源”和“苗条”这两个词可以在该页面上找到。
按照与上次相同的方式运行测试,然后惊叹于你新掌握的技能吧!
结论
您已经了解了使用 Cypress 编写简单的端到端测试来验证 Web 应用程序的正确性是多么容易。我们仅仅触及了 Cypress 功能的冰山一角。
例如,您甚至可以查看测试的屏幕截图并观看录制的视频cypress/videos。您可以定义自定义命令以避免代码重复,使用 fixtures 模拟 API 响应数据等等。
编写完善的端到端测试可以节省您大量的开发时间,并帮助您在合并到生产环境之前发现错误和意外行为。首先,请阅读Cypress 文档并进行实践操作,直到您能够熟练地编写实际测试为止。
插件:LogRocket,一款用于 Web 应用的 DVR

LogRocket是一款前端日志工具,可让您重现问题,如同在您自己的浏览器中发生一样。无需猜测错误原因,也无需用户提供屏幕截图和日志转储,LogRocket 即可让您重现会话,快速了解问题所在。它与任何框架的应用程序完美兼容,并提供插件来记录来自 Redux、Vuex 和 @ngrx/store 的额外上下文信息。
除了记录 Redux 操作和状态之外,LogRocket 还会记录控制台日志、JavaScript 错误、堆栈跟踪、包含标头和正文的网络请求/响应、浏览器元数据以及自定义日志。它还会对 DOM 进行插桩,记录页面上的 HTML 和 CSS,即使是最复杂的单页应用程序,也能生成像素级精确的视频。
免费试用。
文章《如何使用 Cypress 编写有用的端到端测试》最初发表于LogRocket 博客。
文章来源:https://dev.to/bnevilleoneill/how-to-write-useful-end-to-end-tests-with-cypress-mmk



