使用Protractor进行E2E测试时,似乎每行代码都需要await,当
SELENIUM_PROMISE_MANAGER: false
时。
下面这个例子有更好的方法吗?
最初我使用的是
SELENIUM_PROMISE_MANAGER: false
,但在需要使用条件WebElement.isPresent()
时遇到了问题。承诺经理无法解决 isPresent()
的承诺,只能继续执行。所以现在考虑使用 async/await。
describe('Home Page', async () => {
beforeAll(async () => {
await loginPage.loadPage(); // methods defined in Page Object
await loginPage.login(); // uses WebElement.sendKeys() and Webelement.submit()
await homePage.closeModal();
});
it('should fill a form', async () => {
await $('#field1').clear();
await $('#field1').sendKeys('hello');
await $('#field2').clear();
await $('#field2').sendKeys('world');
$('form').submit();
}
}
如果几乎每一行都需要等待,那么我在这里缺少什么吗?
使用 async/await 时,除了在调用每个函数之前放置
await
之外,别无他法,因为在 E2E 测试中,您需要确保所有内容都按特定顺序运行。//declare this somewhere else:
this.formFill = async () => {
await $('#field1').clear();
await $('#field1').sendKeys('hello');
await $('#field2').clear();
await $('#field2').sendKeys('world');
await $('form').submit();
};
然后在
it
块内调用它:
it('should fill a form', async () => {
await this.formFill();
});
我们无法避免它,因为它有充分的理由。首先我们需要了解JavaScript是异步编程语言。当量角器最初使用时,我们必须使用Promises()来编写端到端测试用例,并且由于 Promise 链(多个“then”),很难理解和调试测试代码。为了克服这个问题 Protractor 引入了Promise Manger。它解决了 Promise 链的问题,但是调试测试代码很困难,我们需要做一些显式的操作来调试测试代码。 当 ES2017 引入 async/await 时,它实际上解决了 Promises 链的问题,所以不用写
Using Promises
A().then( () => {
B().then( () => {
C().then( () => {
});
});
});
Using async/await
async func() {
await A();
await B();
await C();
}
await在这里的作用是什么? 函数 A()、B()、C() 仍然返回 Promise 的对象,但在内部等待 Promise 解析/拒绝,然后再移动到下一行。一旦 Promise 解析,它就会获取值然后执行下一行。因此,在每个返回 Promise 的函数之前编写 async/await 非常重要。
让我们看一下您提到的代码
等待loginPage.login(); -> WebElement.sendKeys();和 Webelement.submit();
如果我们检查 IWebelement 类中 sendKeys() 和 Submit() 函数的定义,那么它看起来像这样
sendKeys(...var_args: Array<string|number|promise.Promise<string|number>>): promise.Promise<void>;
submit(): promise.Promise<void>;
在前面的代码片段中我们可以看到两个函数都返回 Promise。如果我们在这些之前不使用await,那么它将无法正确执行代码并移至下一行。
结论是避免或不避免“await”取决于函数的返回类型。如果它不是承诺,那么你可以避免,如果函数返回承诺,那么永远不要避免它。
你可以到处写所有“等待”,但最终它不会更容易阅读和支持。
只是为了练习。有了这个:
await $('#field1').clear();
await $('#field1').sendKeys('hello');
await $('#field2').clear();
await $('#field2').sendKeys('world');
可以转化为操作的定义。
[
['#field1', $.clear, undefined],
['#field1', $.sendKeys, 'hello'],
['#field2', $.clear, undefined],
['#field2', $.sendKeys, 'world'],
]
然后通过一些东西来一一等待他们......这不是更好。是的? :D
(代码仅用于概念)