乐闻世界logo
搜索文章和话题

如何在使用 Cypress 执行所有测试代码之前执行公共代码?

5 个月前提问
3 个月前修改
浏览次数72

6个答案

1
2
3
4
5
6

在Cypress中,要在所有测试运行之前执行一些公共代码,我们通常使用beforebeforeEach钩子。before钩子在测试文件中的所有测试运行之前执行一次,而beforeEach钩子则在每个测试用例运行之前都会执行。

这里有个示例:

如果您想在所有测试前只执行一次某些代码,您可以在测试文件的顶层使用before钩子:

javascript
// 在所有测试前只执行一次 before(() => { // 这里可以放置你的公共代码,比如: // 登录操作 cy.login('username', 'password'); // 假设你有一个封装好的登录命令 // 设置测试数据或者环境 cy.setupTestData(); });

如果需要在每个测试用例之前执行代码,可以使用beforeEach钩子:

javascript
// 在每个测试用例之前都执行 beforeEach(() => { // 这里可以放置你的公共代码,比如: // 每次都要确保从登陆页面开始 cy.visit('/login'); // 访问登录页面 // 你可能需要清除浏览器的localStorage或cookies cy.clearLocalStorage(); cy.clearCookies(); // 每个测试用例都需要的初始化操作 cy.initializeTestContext(); });

这些钩子应该放在你的测试文件顶部,通常在描述测试套件的describe块外面或里面。将它们放在describe块外面意味着它们会在该文件中定义的所有describe块之前运行。放在describe块内部,则只会影响该describe块中的测试用例。

另外,如果你有多个测试文件,并且希望有一些代码在这些测试文件中的每个文件执行前都运行一次,你可以使用Cypress的support文件夹中的index.js文件。在那里放置的代码会在每个测试文件执行前运行。

例如,在cypress/support/index.js文件中:

javascript
// 这将在每个测试文件之前执行一次 before(() => { // 公共初始化代码,比如设置API服务器的状态 cy.initializeApiServer(); }); // 这将在每个测试文件的每个测试用例之前执行 beforeEach(() => { // 通用的每个测试用例前的逻辑,比如登录 cy.loginToApplication(); });

记得在使用这些钩子时要注意它们的作用域和执行顺序,以确保测试环境的正确设置。

2024年6月29日 12:07 回复

Short answer: You can write your login command in a before hook within the supportFile (the file that is loaded automatically before your other spec files). This before hook will run before any of the code in your other test files.


Recommendations: That being said, this approach leaves little flexibility for variation in your individual test files that you may want in the future like:

  • What if you want to seed the database differently for one test?
  • What if you want to log in as a different user with different permissions?
  • What if you need to do something in onBeforeLoad once?

I would recommend just having the login command in a before hook in each individual spec file.

I would also further recommend having your login command in a beforeEach hook to avoid sharing any state in between tests.

2024年6月29日 12:07 回复

Now in Cypress v12 the appropriate way to do this is with the Before Run API.

cypress.config.js

shell
const { defineConfig } = require('cypress') module.exports = defineConfig({ // setupNodeEvents can be defined in either // the e2e or component configuration e2e: { setupNodeEvents(on, config) { on('before:run', (details) => { /* code that needs to run before all specs */ }) }, experimentalInteractiveRunEvents: true, // use for cypress open mode }, })
2024年6月29日 12:07 回复

I would login before EACH test because there could be things that happen in a previous test that affects the results of the current test. With a fresh login, you're starting with a clean state every time. If you want to test a "chain" of unrelated actions (action A THEN action B), then write that as a separate test, but have basic functionality in individual tests.

shell
describe('/page'), () => { beforeEach(() => { cy.login() // custom command that handles login w/o UI cy.visit('/page') // go to the page you are testing }) // tests })

You should include a beforeEach block in every test file. This block should login and navigate to the page in question.

2024年6月29日 12:07 回复

cypress/support/e2e.ts

shell
before(() => { // do stuff })

Use before to run 1-time before every test or use beforeEach. to run before each individual test.

2024年6月29日 12:07 回复

你的答案