赛普拉斯:为数组的每个元素创建一个 it 测试

Cypress: create an it test foreach element of an array

我有一个字符串数组,它们是指向同一网站不同页面的链接;对于这些网页中的每一个,我都对其进行了多次测试,并且对于每个页面,我都在页面的不同 HTML 块上进行了迭代(所有页面都具有相同的块 ID)。

例如,我有 10 个页面描述了 10 个不同的城市;所有页面都有 9 个具有相同 ID 的相同 html 块(它们都来自相同的模板)。我检查每个 id 中是否有几个单词。

我真的做到了;我需要做的是为每个元素创建一个 it 测试。我会尽力解释得更好。

主对象中有一系列数组,所以我有一个 urls 对象,如:

urls: {
    cities: [...],
    secondArr: [...],
    thirdArr: [...]
}

我对 urls.cities 数组感兴趣。

这是城市数组的一个对象:

urls.cities: [{
        city: "Miami"
        discipline: "no-discipline"
        type: "main"
        url: "https://myWebsite.com/miami/"
    }, 
    ...]

我做了类似的事情:main.test.js

it('should retrieve generated pages', () => {

    [...]

    // executing tests for cities
    urls.cities.forEach(elem => {
      cy.visit(elem.url)

      let ids = idsInAllPages   // there's a const idsInAllPages = ['id1', 'id2', ...] on top of the code
      ids.forEach(id => {
        // i get the webelement matching the id, with cypress
        cy.get(id).then(webElem => {
          checkAllWebElementsOfCityUrl(webElem, elem, id)
        })
      })
    })
})

checkAllWebElementsOfCityUrl() 函数中我做了几件事,包括一个 forEach 循环来测试每个 html 块代码(如果需要我可以添加代码,它有点长无论如何都要解释一下,因为我要从 JSON 文件中检查单词,并将它们与 html 块中的内容进行比较。

一切正常,但我的问题是它是单个 it('...') 块:所以如果发现错误,所有后续测试都不会完成。

因此,我需要创建一个 it 测试数组的 forEach 元素。

类似

it('should retrieve generated pages', () => {

    [...]

    // executing tests for cities
    urls.cities.forEach(elem => {
      it('should test a city', () => {
        cy.visit(elem.url)

        let ids = idsInAllPages
        ids.forEach(id => {
          cy.get(id).then(webElem => {
            webpageshelp.checkAllWebElementsOfCityUrl(webElem, elem, id)
          })
        })
      })
    })
})

但是这段代码不起作用,它完全跳过了 it test inside 循环。 有什么办法吗?

更新:

我之前没有提到,但是我发现上面的代码可以工作。 我的问题是,因为我必须从在线 XML 文件中检索 urls 列表并将其转换为一个对象(上面描述的对象 urls),所以我将所有代码包装在一个请求中,然后是一个.then(),喜欢

cy.request('https://myWebsite.com/urlslist.xml').then(
urls => {
    urls.cities.forEach(elem => {
          it('should test a city', () => {
            cy.visit(elem.url)
          })
    })
})

cy.request 更改为您想要检索文件的任何内容,您总是会在 .then() 块中结束,即使使用 cy.task.

NOR 使用 before() 块可以提供帮助,因为没有任何方法可以将数据带到 before() 之外和 describe() 块内(不是 it()块)。

我终于找到了解决办法,我会post下这个页面。

我终于找到了解决办法:

自 2021 年 4 月 12 日起,赛普拉斯添加了一项实验性支持,可在您的规范文件(*.spec.js*.test.js 或您的测试文件)启动之前执行代码。

更多信息here

有趣的是这个选项:experimentalInteractiveRunEvents,它允许 before:spec 执行代码。

您需要在 cypress.js 文件中添加选项

{
  "...": "...",
  ...,

  "experimentalInteractiveRunEvents": true
}

然后,在 /plugins/index.js 文件中,我添加了

module.exports = (on, config) => {
      on('...', ...),

    // executes function before running the test file - EXPERIMENTAL
      on('before:spec', async () => {
        let data = await webpageshelp.retrieveAndConvertXMLToJSON()
        return fs.writeFileSync('data.json', data)
      })
}

async/await函数是在另一个js文件中定义的函数,它下载XML文件并将其转换为JSON:

async function retrieveAndConvertXMLToJSON() {
  const http = axios.create({ baseURL: 'http://myWebsite.com' })

  try {
    const { data } = await http.get('/myfile.xml')
    let jdata = convert.xml2js(data, { compact: true, spaces: 4 })
    let rawUrls = []
    jdata.urlset.url.forEach(url => {
      rawUrls.push(url.loc._text)
    })
    return JSON.stringify(rawUrls)
  } catch (error) {
    throw err
  }
}

关于url.loc._text的逻辑是由于xml的配置; xml2js 是一个 plugin,可以将 xmls 转换为 json。

此时,用于主mytest.test.js文件

const rawUrls = require('../../../data.json')

在文件的顶部,然后

describe('my tests', () => {
    // some more work with my urls
    let urls = filterUrls(rawUrls)    // a function that removes unuseful urls

    urls.cities.forEach(elem => {
      it(`TEST for city ${elem.city} and discipline ${elem.discipline}`, () => {
        console.log('yayyy', elem)
      })
    })
})

瞧,它运行了!

唯一的缺点是文件下载只发生一次,当您在 运行 cypress open 之后单击您的测试文件时;因此,如果您只是更改代码或使用刷新按钮重新启动测试,它将不会再次下载该文件。您必须关闭浏览器并再次单击您的测试,但这对我来说是可以接受的,因为在线文件不会经常更改。