赛普拉斯:为数组的每个元素创建一个 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
之后单击您的测试文件时;因此,如果您只是更改代码或使用刷新按钮重新启动测试,它将不会再次下载该文件。您必须关闭浏览器并再次单击您的测试,但这对我来说是可以接受的,因为在线文件不会经常更改。
我有一个字符串数组,它们是指向同一网站不同页面的链接;对于这些网页中的每一个,我都对其进行了多次测试,并且对于每个页面,我都在页面的不同 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
之后单击您的测试文件时;因此,如果您只是更改代码或使用刷新按钮重新启动测试,它将不会再次下载该文件。您必须关闭浏览器并再次单击您的测试,但这对我来说是可以接受的,因为在线文件不会经常更改。