[测试angular 2 web应用]
当browser.ignoreSynchronization = false
设置为true时,这个错误发生,这个错误没有发生,为什么会这样?
我也有useAllAngular2AppRoots: true
设置在我的量角器配置
Protractor运行在WebDriverJS之上。WebDriverJS是一个Javascript接口,相当于Java的Webdriver,它可以让你以编程方式控制浏览器,这反过来又有助于编写自动化的测试用例
使用WebDriverJS测试Angular应用的问题在于,Angular有自己的事件循环,与浏览器的事件循环是分开的。这意味着当你执行WebDriverJS命令时,Angular可能还在做它自己的事情。
解决这个问题的一种方法是告诉WebDriverJS等待一段任意的时间(比如3000ms),这样Angular就可以完成渲染工作,但这不是正确的做法。因此,创建Protractor是为了让你的测试与Angular的事件循环同步,方法是在Angular处理完前一个命令之后再运行下一个命令。
但是这里有一个问题,当你测试非angular应用程序时,即使没有angular完成它的循环,Protractor也会一直等待angular同步,并会抛出一个你正在观察的错误!
因此,对于非Angular页面,你可以通过设置browser.ignoreSynchronization = true
来告诉Protractor不要寻找Angular——这实际上意味着你只是在使用WebDriverJS。
所以,当Protractor在你的页面上找不到Angular时,把它添加到你的配置中,你就放弃了所有让测试Angular应用比纯WebDriverJS更容易的东西。是的,添加浏览器。在你所有的命令之后睡觉可能会工作,但它很麻烦,一旦Angular花的时间超过了你设置的暂停时间,它就会中断,让你的测试花的时间过长。
结论:仅在测试不使用Angular的页面时使用browser.ignoreSynchronization = true
。
https://vincenttunru.com/Error-Error-while-waiting-for-Protractor-to-sync-with-the-page/
您绝对应该确保您的页面在测试中只加载一次。我们在一个登录模型中遇到了这个问题,它会导致加载的页面在第一次加载完成后立即重新加载,这是在Angular 2应用程序的引导代码中。这会导致各种不可预测的行为,如测试因超时或上述错误而失败,或运行正常。
所以,在测试之前,确保你有一个一致的页面生命周期。
对@ram-pasala的观点进行扩展:
解决这个问题的一种方法是告诉WebDriverJS等待任意数量的时间(例如3000ms),以便Angular完成渲染工作,但这不是正确的做事方式
下面是等待函数变得可用的样子。它是用于TestCafe的,但应该很容易适应其他测试框架:
export const waitForAngular = ClientFunction((timeoutMs: number = 60_000) => {
const waitForGetAllAngularTestabilities = (timeoutMs: number) => {
if (timeoutMs <= 0) throw new Error('Waited for window.getAllAngularTestabilities, but timed out.')
const win = (window as any);
if (win.getAllAngularTestabilities) {
return Promise.resolve(win.getAllAngularTestabilities)
} else {
return new Promise(res => setTimeout(() => res(true), 100)).then(() => waitForGetAllAngularTestabilities(timeoutMs - 100))
}
}
return waitForGetAllAngularTestabilities(30_000).then((getAllAngularTestabilities) => {
return Promise.all(
getAllAngularTestabilities().map(
(t) =>
new Promise((res, rej) => {
setTimeout(() => rej(`Waited ${timeoutMs}ms for Angular to stabilize but timed out.`), timeoutMs);
return t.whenStable(() => {
res(true);
console.log('Angular stable');
});
}),
),
)
})
});