如何在使用 Cypress 运行第一次测试之前运行命令

问题描述 投票:0回答:1

我想在第一次测试之前执行一个设置夹具的命令。但它不应该在每个测试之前运行 - 就在第一个测试之前。

我正在尝试获取已部署应用程序的功能标志,我正在对其进行测试(本地、临时或生产)。在应用程序中,功能标志存储在

window
对象上:
window.featureFlags
。我的
setupFixtures
函数应该将这些功能标志保存到我的
fixtures/feature-flags.json
中。这样,我就可以根据部署的代码查看是否启用了某个功能。

然后我可以将其添加到我的所有测试中:

beforeEach( function(){
  if( !isFeatureEnabled( 'FEATURENAME' ) ){
    this.skip();
  }
});

这意味着它将从给定的部署代码中获取featureName。如果未启用 featureName,那么它将自动跳过该测试。

  • 如果我运行一个名为

    test-header.cy.ts
    的测试,那么我希望我的测试能够执行以下操作:

    • 获取功能标志并将其保存到
      fixtures/feature-flags.json
    • 运行
      test-header.cy.ts
      测试
  • 如果我有三个测试:

    test-x.cy.ts
    test-y.cy.ts
    test-z.cy.ts
    ,那么我希望它这样做:

    • 获取功能标志并将其保存到
      fixtures/feature-flags.json
    • 运行
      test-x.cy.ts
      测试
    • 运行
      test-y.cy.ts
      测试
    • 运行
      test-z.cy.ts
      测试

我该怎么做?

我已经尝试过:

  1. before
    部分添加到我的
    e2e.ts
    文件中:

    这需要定义一些辅助函数和任务,但如果我这样做:

    // Add isFeaturedEnabled globally (so we don't need to import it every time)
    function isFeatureEnabled(featureName) {
      if (!globalThis.featureFlags) {
        throw new Error('Feature flags are not set');
      }
    
      const feature = globalThis.featureFlags.find((feature) => feature.name === featureName);
      return Boolean(feature && feature.enabled);
    }
    
    globalThis.isFeatureEnabled = isFeatureEnabled; // Attach the function to the global scope
    // END OF: Add isFeaturedEnabled globally
    
    before(() => {
      const filePath = 'cypress/fixtures/tmp/featureFlags.json';
    
      // Reset featureFlags, to ensure to get the latest one
      cy.task('fileExists', filePath)
        .then((exists) => {
          if (exists) {
            cy.exec(`rm ${filePath}`);
          }
        })
        .then(() => {
          cy.visit('/');
          cy.window().then((win) => {
            if (win.featureFlags && win.featureFlags.length > 0) {
              cy.writeFile(filePath, win.featureFlags);
              globalThis.featureFlags = win.featureFlags;
            } else {
              cy.writeFile(filePath, []);
              globalThis.featureFlags = [];
            }
          });
        });
    });
    

    这正在起作用。但这意味着它在每次单独测试之前都会生成一个新的

    cypress/fixtures/tmp/featureFlags.json
    ,这浪费了相当多的时间。特别是因为它每次都需要重新加载主页(以便可以访问窗口对象)。

  2. 制作“设置测试”bash 脚本或其他内容

    我可以制作一个小脚本,在运行测试之前设置功能标志固定装置。这也是一个不错的选择,但它也会增加我的同事在不同的环境中运行时忘记重新运行该选项的可能性,从而给他们带来误报。

cypress
1个回答
1
投票

如果您只想针对运行中的所有规范运行代码一次,则应使用 Before Run API 而不是

before()
钩子。

由于运行在Node进程中,所以使用fs.unlink来删除文件。

文档中的示例:

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
  },
})

但是,您的代码看起来完全不必要,我会在每次访问时将

win.features
属性读入环境变量

参见

Cypress.env

范围

使用 Cypress.env 设置的环境变量仅在当前规范文件的范围内。

Cypress 单独运行每个规范文件:

浏览器在规范之间退出。

cy.visit('http://localhost:3000/#/users', { onLoad: (win) => { const flags = win.featureFlags || [] // default to empty Cypress.env('flags', flags) }, })
提供

Cypress.env()

是为了避免因测试清理而造成的全球污染和意外Bug。您当前的方法不太可能在测试隔离最佳实践中幸存下来。

© www.soinside.com 2019 - 2024. All rights reserved.