使用“运行所有测试”时按标签(例如 cypress-grep)过滤测试

Flo*_*e.P 7 cypress cypress-grep

根据我的问题在 Cypress 版本 10+ 中使用“运行所有测试”过滤测试,我们可以将标记的测试过滤器应用到 Cypress GUI 吗?

例如,如果我将cypress-grep添加到项目中,我可以像这样对每个测试使用标签

it('tests for smoke', {tags: ['@smoke']}, () => {
})

it('tests for fire', {tags: ['@fire']}, () => {
})
Run Code Online (Sandbox Code Playgroud)

npx cypress open --env grep=@smoke,grepFilterTests=true然后我可以从脚本运行。

是否可以扩展“使用过滤器运行所有测试”以在 GUI 中输入标签@smoke并临时运行冒烟测试?

我意识到上面的 npx 命令可以完成相同的工作,但是当我只想在开发更改期间运行我的 Smoke 时,步骤很长并且浪费时间。

Fod*_*ody 6

如果遵循为标签添加前缀的约定,您可以按标签动态过滤测试@

cypress-grep通常在 中调用cypress/support/e2e.js,但如果您在生成的测试脚本的顶部调用它,它也可以工作。

这是生成的测试的模式。前几行调用cypress-grep以启用标记过滤@smoke

// generated script for specs filtered with "@smoke"

import cypressGrep from '@cypress/grep';
Cypress.env('grepTags', '@smoke');
cypressGrep();

context('cypress/e2e/login/login.cy.js', () => 
  require('../login/login.js'))
context('cypress/e2e/shopping-cart/checkout.cy.js', () => 
  require('../shopping-cart/checkout.cy.js'))
Run Code Online (Sandbox Code Playgroud)

过滤规格的任务

要动态过滤标签,您需要将一些功能复制cypress-grep到您的项目代码中。

首先,您需要一项任务来找出哪些规格具有您想要的标签。

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      on('task', {
        specsWithTag: async ({tag}) => {
          const {globbySync} = await import('globby')
          const specFiles = globbySync(config.specPattern, {
            cwd: __dirname,
            ignore: config.excludeSpecPattern,
          })
          const regex = new RegExp(`{\\s*((tags)|(tag)):\\s*[',"]${tag}[',"]\\s*}`)
          return specFiles.filter(spec => {
            const fullPath = path.join(__dirname, spec)
            const specCode = fs.readFileSync(fullPath, { encoding: 'utf8' })
            return regex.test(specCode)
          })
        }
      })
      return config
    },
  }
})
Run Code Online (Sandbox Code Playgroud)

对测试生成器的更改

然后您需要增强_generate.cy.js规范来处理标签。

使用cypress-if可以轻松地根据输入的过滤器对代码进行分支。

import 'cypress-if'

const specExtension = '.cy.js'

const filter = Cypress.$(parent.document.body)
  .find('div#app')
  .find('#inline-spec-list-header-search')
  .val()

const specList = Cypress.$(parent.document.body)
  .find('div#app .specs-list-container ul:eq(0) li')
  .map((index,el) => {
    const text = el.innerText.replace('\n', '').replace('\\', '/')
    const path = Cypress.$(el).find('a').attr('href').split('?file=')[1]
    return {
      text,
      path
    }
  })
  .filter((index, item) => {
    return item.text.endsWith(specExtension) && !item.text.startsWith('_')
  })
  .map((index,item) => item.path)
  .toArray()

const filterHasTag = (filter) => filter && filter.startsWith('@')

const generate = (specList, filter) => {
  const isTag = filterHasTag(filter)
  const indexSpecName = filter ? `_run-[${filter}]-${isTag ? 'tag' : 
    'filter'}${specExtension}` : `_run-all${specExtension}`
  const msg = `Processing ${isTag ? 'tag' : filter ? 'filter' : 'all'}: ${filter}`
  cy.log(msg)

  let content = `// generated script for specs filtered with "${filter}"\n\n`
  if (isTag) {
    content += `import cypressGrep from '@cypress/grep';\n`
    content += `Cypress.env('grepTags', '${filter}');\n`
    content += 'cypressGrep();\n\n'
  }
  content += specList.map(specPath => {
    return `context('${specPath}', () => require('..${specPath.replace('cypress/e2e', '')}'))`  
  }).join('\n')
  cy.writeFile(`./cypress/e2e/_generated-tests/${indexSpecName}`, content)
}

it('', () => {
  cy.wrap(filterHasTag(filter), {log:false})
    .if()
    .task('specsWithTag', {specs: specList, tag: '@smoke'})
    .then(tagged => generate(tagged, filter))
    .else()
    .then(() => generate(specList, filter))
})
Run Code Online (Sandbox Code Playgroud)