Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Cypress:为数组的每个元素创建it测试_Javascript_Mocha.js_Cypress - Fatal编程技术网

Javascript Cypress:为数组的每个元素创建it测试

Javascript Cypress:为数组的每个元素创建it测试,javascript,mocha.js,cypress,Javascript,Mocha.js,Cypress,我有一个字符串数组,它们是指向同一网站不同页面的链接;对于这些网页中的每一个,我都会对其执行一些测试,对于每个页面,我会在页面的不同HTML块上迭代(所有页面都有相同的块ID) 例如,我有10页描述了10个不同的城市;所有页面都有9个id相同的html块(它们都来自同一模板)。我检查每个ID中是否有几个单词 我真的做到了;我需要做的是为每个元素创建一个it测试。我会尽量解释得更好 主对象中有一系列数组,因此我有一个url对象,如: urls: { cities: [...], s

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

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

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

主对象中有一系列数组,因此我有一个
url
对象,如:

urls: {
    cities: [...],
    secondArr: [...],
    thirdArr: [...]
}
我对
url.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
test
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测试。 有什么办法吗

更新:

我以前没有提到过,但我发现上面的代码是有效的。 我的问题是,因为我必须从一个在线XML文件中检索URL列表并将其转换为一个对象(上面描述的对象
URL
),所以我将所有代码包装在一个请求中,后面跟着一个
.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

使用
before()
块也没有帮助,因为无法将数据带到
before()
块之外和
descripe()
块内部(不是
it()
块)


我终于找到了一个解决方案,我将在此页面上发布。

我终于找到了一个解决方案:

自2021年4月12日起,cypress在spec文件(
*.spec.js
*.test.js
或任何测试文件)启动之前添加了一个实验性支持来执行代码

更多信息

有趣的是这个选项:
experimentalInteractiveRunEvents
,它在执行代码之前启用
: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._文本的逻辑是由xml配置决定的;xml2js是一种将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
后单击测试文件时,文件下载只发生一次;因此,如果您只是更改代码或使用刷新按钮重新启动测试,它将不会再次下载该文件。您必须关闭浏览器并再次单击测试,但这对我来说是可以接受的,因为在线文件不会如此频繁地更改。

为什么不将循环移到
it
url.cities.forEach((elem)=>it(“…”,()=>)
)?嗯,我可以尝试,但意味着执行
描述
块中的代码(注:我写的最后一段代码,循环中带有
it
的那段代码不起作用)@jornsharpe我现在试过了,但不起作用。这些代码块像
url.cities.forEach(elem=>{it('TEST',()=>{console.log('yayy')})不幸的是,
从未被执行过!这应该是可行的,除非将console.log更改为
expect(true).to.eq(true)
-可能因为测试不包含任何断言而忽略了测试。你是对的,但是我发现这并不容易。为了简化,我没有提到URL列表是由xml文件在线获取并在对象中转换的。我想我会更新问题,无论如何,问题是我无法更新在不使用
.then()
函数的情况下检索该文件,并将所有代码放入该
函数中。then()
-如果我将一个变量放在外部,并将结果保存在
函数中。then()
中,则不会保存数据-。我不能这样做,因为我需要执行多个
it
测试。