如何将配置中的对象值与网站上的 href 进行比较
How to compare object values in a config to hrefs on a website
这是我之前发布的问题的后续
在这个问题中,我试图将网站上的 href 值测试为配置文件中存储的内容。
URL: https://wdwthemeparks.com
配置文件(位于Resources/config.json)
{
"url": "https://wdwthemeparks.com",
"topMenuNav": {
"All": "/all/",
"News": "/news/",
"Press Releases": "/press/",
"Rumors": "/rumors/",
"About": "/about/",
"Contact": "/contact/",
"Refurbishments": "/refurbishments/"
}
}
选择器位于 Objects/header.js
import { Selector, t } from 'testcafe';
class Header {
constructor() {
this.topMenuNav = Selector('.top-header-menu')
this.topMenuNavItem = Selector(this.topMenuNav).find('a');
}
}
export default new Header();
测试位于 Tests/topMenu.js
import { Selector } from 'testcafe';
import Header from '../Objects/header';
const config = require('../Resources/config.json');
fixture `Check Top Menu`
.page(config.url)
.beforeEach( async t => {
await t.maximizeWindow();
});
test
.meta({ desktop: 'true'})
('Check Top Menu Items', async t => {
const topMenuNavKeys = Object.keys(config.topMenuNav);
const topMenuNavValues = Object.values(config.topMenuNav);
await t.expect(Header.topMenuNav.visible).ok('Top Menu Nav is NOT visible');
for (const key of topMenuNavKeys) {
await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
}
// THE PROBLEM I AM HAVING IS HERE IN THIS PART OF THE CODE
for (const value of topMenuNavValues) {
await t.expect(Header.topMenuNavItem.getAttribute('href')).contains(value, `"${value}" Top Menu Nav value does NOT match config`);
}
});
我从 TestCafe 收到以下错误消息:
Running tests in:
- Chrome 85.0.4183.83 / Windows 10
Check Top Menu
ReExecutablePromise { _then: [], _fn: [Function], _taskPromise: null }
ReExecutablePromise { _then: [], _fn: [Function], _taskPromise: null }
× Check Top Menu Items
1) AssertionError: "/news/" Top Menu Nav value does NOT match config: expected 'https://wdwthemeparks.com/all/' to include '/news/'
+ expected - actual
-'https://wdwthemeparks.com/all/'
+undefined
Browser: Chrome 85.0.4183.83 / Windows 10
32 | await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
33 | }
34 |
35 | for (const value of topMenuNavValues) {
36 | console.log(Header.topMenuNavItem.getAttribute('href'));
> 37 | await t.expect(await Header.topMenuNavItem.getAttribute('href')).contains(value, `"${value}" Top Menu Nav value does NOT match config`);
38 | }
39 |});
40 |
at <anonymous> (C:\Users\J\Repos\wdwthemeparks-automation\Tests\topMenu.js:37:69)
1/1 failed (7s)
我不确定我做错了什么。
this.topMenuNav = Selector('.top-header-menu')
this.topMenuNavItem = Selector(this.topMenuNav).find('a');
而你的 DOM 是:
<ul id="menu-td-demo-top-menu" class="top-header-menu sf-js-enabled"><li id="menu-item-30278" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-first td-menu-item td-normal-menu menu-item-30278"><a href="https://wdwthemeparks.com/all/">All</a></li>
<li id="menu-item-23037" class="menu-item menu-item-type-custom menu-item-object-custom td-menu-item td-normal-menu menu-item-23037"><a href="/news/">News</a></li>
<li id="menu-item-30297" class="menu-item menu-item-type-custom menu-item-object-custom td-menu-item td-normal-menu menu-item-30297"><a href="/press/">Press Releases</a></li>
<li id="menu-item-23041" class="menu-item menu-item-type-custom menu-item-object-custom td-menu-item td-normal-menu menu-item-23041"><a href="/rumors/">Rumors</a></li>
<li id="menu-item-10635" class="menu-item menu-item-type-post_type menu-item-object-page td-menu-item td-normal-menu menu-item-10635"><a href="https://wdwthemeparks.com/about/">About</a></li>
<li id="menu-item-41" class="menu-item menu-item-type-post_type menu-item-object-page td-menu-item td-normal-menu menu-item-41"><a href="https://wdwthemeparks.com/contact/">Contact</a></li>
<li id="menu-item-30288" class="menu-item menu-item-type-post_type menu-item-object-page td-menu-item td-normal-menu menu-item-30288"><a href="https://wdwthemeparks.com/refurbishments/">Refurbishments</a></li>
</ul>
所以这部分 Header.topMenuNavItem.getAttribute('href')
将始终给您第一个 a
标签,即:
<a href="https://wdwthemeparks.com/all/">All</a>
所以第一次迭代实际上通过了,但是当循环达到/news/
值时,它失败了。
基本上你只是迭代你的配置值,而不是你在网站上找到的标签,因为 topMenuNavItem
returns 总是相同 tag/selector.
因此您的整个测试文件可能如下所示:
import { Selector } from 'testcafe';
import Header from '../Objects/header';
const config = require('../Resources/config.json');
fixture `Check Top Menu`
.page(config.url)
.beforeEach( async t => {
await t.maximizeWindow();
});
test
.meta({ desktop: 'true'})
('Check Top Menu Items', async t => {
const topMenuNavKeys = Object.keys(config.topMenuNav);
await t.expect(Header.topMenuNav.visible).ok('Top Menu Nav is NOT visible');
for (const key of topMenuNavKeys) {
await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
await t.expect(Header.topMenuNavItem.withText(key).getAttribute('href')).contains(config["topMenuNav"][key], `"${config["topMenuNav"][key]}" Top Menu Nav value does NOT match config`);
}
});
你应该做的是:
- 将测试用例简化到最低限度,也许首先去掉不起作用的部分并确认至少有一部分起作用
- 使用
console.log()
或其他方法提高知名度
- 验证测试用例的每一行,你需要知道每一行的作用
- 阅读文档
如果您尝试获取 属性 或调用匹配多个元素的选择器的方法,TestCafe 将使用匹配集中的第一个元素作为目标。由于第二个断言中缺少 withText(itemText)
,因此您的循环始终断言相同的元素。
expect.contains
断言的 diff 视图有一个错误 (DevExpress/testcafe#5473),因此可以在断言消息中找到线索:
AssertionError: ...: expected 'https://wdwthemeparks.com/all/' to include '/news/'
此外,我不建议在传递选择器属性和方法时使用 await
,因为它会禁用 Smart Assertion Query Mechanism。在当前场景下这不是一个交易破坏者,但如果您遵循此建议,您可以在更复杂的场景中显着提高测试稳定性。
以下测试代码似乎对我来说工作正常:
for (const [key, value] of Object.entries(config.topMenuNav)) {
await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
await t.expect(Header.topMenuNavItem.withText(key).getAttribute('href')).contains(value, `"${value}" Top Menu Nav value does NOT match config`);
}
这是我之前发布的问题的后续
在这个问题中,我试图将网站上的 href 值测试为配置文件中存储的内容。
URL: https://wdwthemeparks.com
配置文件(位于Resources/config.json)
{
"url": "https://wdwthemeparks.com",
"topMenuNav": {
"All": "/all/",
"News": "/news/",
"Press Releases": "/press/",
"Rumors": "/rumors/",
"About": "/about/",
"Contact": "/contact/",
"Refurbishments": "/refurbishments/"
}
}
选择器位于 Objects/header.js
import { Selector, t } from 'testcafe';
class Header {
constructor() {
this.topMenuNav = Selector('.top-header-menu')
this.topMenuNavItem = Selector(this.topMenuNav).find('a');
}
}
export default new Header();
测试位于 Tests/topMenu.js
import { Selector } from 'testcafe';
import Header from '../Objects/header';
const config = require('../Resources/config.json');
fixture `Check Top Menu`
.page(config.url)
.beforeEach( async t => {
await t.maximizeWindow();
});
test
.meta({ desktop: 'true'})
('Check Top Menu Items', async t => {
const topMenuNavKeys = Object.keys(config.topMenuNav);
const topMenuNavValues = Object.values(config.topMenuNav);
await t.expect(Header.topMenuNav.visible).ok('Top Menu Nav is NOT visible');
for (const key of topMenuNavKeys) {
await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
}
// THE PROBLEM I AM HAVING IS HERE IN THIS PART OF THE CODE
for (const value of topMenuNavValues) {
await t.expect(Header.topMenuNavItem.getAttribute('href')).contains(value, `"${value}" Top Menu Nav value does NOT match config`);
}
});
我从 TestCafe 收到以下错误消息:
Running tests in:
- Chrome 85.0.4183.83 / Windows 10
Check Top Menu
ReExecutablePromise { _then: [], _fn: [Function], _taskPromise: null }
ReExecutablePromise { _then: [], _fn: [Function], _taskPromise: null }
× Check Top Menu Items
1) AssertionError: "/news/" Top Menu Nav value does NOT match config: expected 'https://wdwthemeparks.com/all/' to include '/news/'
+ expected - actual
-'https://wdwthemeparks.com/all/'
+undefined
Browser: Chrome 85.0.4183.83 / Windows 10
32 | await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
33 | }
34 |
35 | for (const value of topMenuNavValues) {
36 | console.log(Header.topMenuNavItem.getAttribute('href'));
> 37 | await t.expect(await Header.topMenuNavItem.getAttribute('href')).contains(value, `"${value}" Top Menu Nav value does NOT match config`);
38 | }
39 |});
40 |
at <anonymous> (C:\Users\J\Repos\wdwthemeparks-automation\Tests\topMenu.js:37:69)
1/1 failed (7s)
我不确定我做错了什么。
this.topMenuNav = Selector('.top-header-menu')
this.topMenuNavItem = Selector(this.topMenuNav).find('a');
而你的 DOM 是:
<ul id="menu-td-demo-top-menu" class="top-header-menu sf-js-enabled"><li id="menu-item-30278" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-first td-menu-item td-normal-menu menu-item-30278"><a href="https://wdwthemeparks.com/all/">All</a></li>
<li id="menu-item-23037" class="menu-item menu-item-type-custom menu-item-object-custom td-menu-item td-normal-menu menu-item-23037"><a href="/news/">News</a></li>
<li id="menu-item-30297" class="menu-item menu-item-type-custom menu-item-object-custom td-menu-item td-normal-menu menu-item-30297"><a href="/press/">Press Releases</a></li>
<li id="menu-item-23041" class="menu-item menu-item-type-custom menu-item-object-custom td-menu-item td-normal-menu menu-item-23041"><a href="/rumors/">Rumors</a></li>
<li id="menu-item-10635" class="menu-item menu-item-type-post_type menu-item-object-page td-menu-item td-normal-menu menu-item-10635"><a href="https://wdwthemeparks.com/about/">About</a></li>
<li id="menu-item-41" class="menu-item menu-item-type-post_type menu-item-object-page td-menu-item td-normal-menu menu-item-41"><a href="https://wdwthemeparks.com/contact/">Contact</a></li>
<li id="menu-item-30288" class="menu-item menu-item-type-post_type menu-item-object-page td-menu-item td-normal-menu menu-item-30288"><a href="https://wdwthemeparks.com/refurbishments/">Refurbishments</a></li>
</ul>
所以这部分 Header.topMenuNavItem.getAttribute('href')
将始终给您第一个 a
标签,即:
<a href="https://wdwthemeparks.com/all/">All</a>
所以第一次迭代实际上通过了,但是当循环达到/news/
值时,它失败了。
基本上你只是迭代你的配置值,而不是你在网站上找到的标签,因为 topMenuNavItem
returns 总是相同 tag/selector.
因此您的整个测试文件可能如下所示:
import { Selector } from 'testcafe';
import Header from '../Objects/header';
const config = require('../Resources/config.json');
fixture `Check Top Menu`
.page(config.url)
.beforeEach( async t => {
await t.maximizeWindow();
});
test
.meta({ desktop: 'true'})
('Check Top Menu Items', async t => {
const topMenuNavKeys = Object.keys(config.topMenuNav);
await t.expect(Header.topMenuNav.visible).ok('Top Menu Nav is NOT visible');
for (const key of topMenuNavKeys) {
await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
await t.expect(Header.topMenuNavItem.withText(key).getAttribute('href')).contains(config["topMenuNav"][key], `"${config["topMenuNav"][key]}" Top Menu Nav value does NOT match config`);
}
});
你应该做的是:
- 将测试用例简化到最低限度,也许首先去掉不起作用的部分并确认至少有一部分起作用
- 使用
console.log()
或其他方法提高知名度 - 验证测试用例的每一行,你需要知道每一行的作用
- 阅读文档
如果您尝试获取 属性 或调用匹配多个元素的选择器的方法,TestCafe 将使用匹配集中的第一个元素作为目标。由于第二个断言中缺少 withText(itemText)
,因此您的循环始终断言相同的元素。
expect.contains
断言的 diff 视图有一个错误 (DevExpress/testcafe#5473),因此可以在断言消息中找到线索:
AssertionError: ...: expected 'https://wdwthemeparks.com/all/' to include '/news/'
此外,我不建议在传递选择器属性和方法时使用 await
,因为它会禁用 Smart Assertion Query Mechanism。在当前场景下这不是一个交易破坏者,但如果您遵循此建议,您可以在更复杂的场景中显着提高测试稳定性。
以下测试代码似乎对我来说工作正常:
for (const [key, value] of Object.entries(config.topMenuNav)) {
await t.expect(Header.topMenuNavItem.withText(key).exists).ok(`"${key}" Top Menu Nav key does NOT match config`);
await t.expect(Header.topMenuNavItem.withText(key).getAttribute('href')).contains(value, `"${value}" Top Menu Nav value does NOT match config`);
}