问题描述
这是我先前发布的问题here
的后续活动在这个问题中,我试图将网站上的href值测试为配置文件中存储的值。
配置文件(位于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`);
}
});
Running tests in:
- Chrome 85.0.4183.83 / Windows 10
Check Top Menu
ReExecutablePromise { _then: [],_fn: [Function],_taskPromise: null }
ReExecutablePromise { _then: [],_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)
我不确定自己做错了什么。
解决方法
如果尝试获取属性或调用与多个元素匹配的选择器的方法,则TestCafe将使用匹配集中的第一个元素作为目标。由于第二个断言中缺少withText(itemText)
,因此您的循环将始终断言相同的元素。
expect.contains
断言的差异视图有一个错误(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`);
}
,
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
总是返回相同的标记/选择器。
因此您的整个测试文件可能如下所示:
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()
或其他方法来提高可见度 - 验证测试用例的每一行,您需要知道每一行的作用
- 阅读文档