selenium-webdriver 的执行顺序(对于 Node JS)
Execution sequence with selenium-webdriver (for Node JS)
我对 selenium-webdriver 命令的执行顺序有点困惑。
以下示例的正确编码是什么。
我想:
- 首先,在文本框中输入文字
- 然后,单击按钮
以下代码是否保证顺序正确?
// Enter the text
driver.findElement(webdriver.By.id('txt'))
.sendKeys('bla bla')
.then(
function() {},
function(err) {
console.log(err);
done(err);
}
);
// Press the button
driver.findElement(webdriver.By.id('btn'))
.click()
.then(
function() {
done();
},
function(err) {
console.log(err);
done(err);
}
);
或者我应该这样做吗?
// Enter the pass
driver.findElement(webdriver.By.id('txt_pass'))
.sendKeys('sifra')
.then(
function() {
// Press the login button
driver.findElement(webdriver.By.id('btn_login'))
.click()
.then(
function() {
done();
},
function(err) {
console.log(err);
done(err);
}
);
},
function(err) {
console.log(err);
done(err);
}
);
如果第二种情况是正确的,当连续需要2个以上的动作时,代码应该怎么写?我会很复杂,必须维护。
更新:
假设现在我想清除在第一个 findElement 中找到的元素 "txt",并在我输入文本之前执行此操作。根据 Louis 的回答,我怀疑它应该是什么像这样:
// Clear the textbox
driver.findElement(webdriver.By.id('txt'))
.clear()
.then(
function() {},
function(err) {
console.log(err);
done(err);
}
);
// Enter the text
driver.findElement(webdriver.By.id('txt'))
.sendKeys('bla bla')
.then(
function() {},
function(err) {
console.log(err);
done(err);
}
);
// go on with the further sequence...
我觉得这不是很好,它太长而且笨拙,尤其是在同一元素上有更多操作的情况下。有没有一种通用的方法可以缩短它,使其更紧凑?
类似链接的东西:
findElement('txt').clear().sendKeys('bla, bla'); // This does not work, as clear is a void
你的第一种方法是正确的。您似乎缺少的信息是 WebDriver 的 JavaScript 实现使用 "promise manager" 为您排序承诺。 这在 "Control Flows" 指南部分。这是一个例子:
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().
withCapabilities(webdriver.Capabilities.chrome()).
build();
// Do not implicitly wait for anything.
driver.manage().timeouts().implicitlyWait(0);
// Set the script wait timeout to 10 seconds.
driver.manage().timeouts().setScriptTimeout(10 * 1000);
driver.get('http://www.example.com');
function err() {
console.log("ERR", arguments);
}
var start = Date.now();
driver.executeAsyncScript(
"var done = arguments[0];" +
"setTimeout(function () { document.body.innerHTML = '<p id=\"foo\"></p>'; done() }, 5000)")
.then(function () {
console.log("created foo!", Date.now() - start);
},
err);
driver.findElement(webdriver.By.tagName("body")).then(function () {
console.log("here", Date.now() - start);
});
driver.findElement(webdriver.By.id("foo")).then(function () {
console.log("found foo!", Date.now() - start);
}, err);
这将向控制台输出以下行,始终以相同的顺序:
created foo! 5639
here 5657
found foo! 5670
数字会有所不同,但它们总是 > 5000,并且彼此非常接近(除非 运行 在超载或慢得离谱的系统上)。首先执行的 executeAsyncScript
是为了说明需要一段时间才能完成的操作 而不是 将允许对同一驱动程序进行后续操作。除了它执行脚本而不是查找元素之外,它与 findElement
没有任何不同:promise 管理器等待直到操作完成,然后才能继续下一个操作,even 如果两个操作没有使用 .then()
.
明确排序
如果 promise 管理器没有一个接一个地对操作进行排序,那么 .findElement(webdriver.By.tagName("body"))
将在异步脚本完成之前执行,并且它会在 "created foo!"
之前打印 "here"
打印到控制台,因为该页面确实有一个 body
元素。
另外,如果承诺管理器没有一个接一个地对操作进行排序,那么最后一个 .findElement
将无法找到 id
值为 foo
的元素。在脚本的早期,我关闭了隐式等待,因此 findElement
调用肯定不会 等待 等待 foo
出现。
在 种情况下,您更希望像在第二个代码段中那样做,但您没有在问题中包含任何明确的理由应该这样做方式。
此外,如果不是 Selenium 的承诺管理器,那么您 必须 执行类似于您的第二个代码段的操作,因为通常没有任何顺序承诺适合您。
关于您关于如何对 clear
和 sendKeys
进行排序的问题,您可以这样做:
driver.findElement(webdriver.By.id('txt')).then(function (el) {
el.clear();
el.sendKeys('bla bla');
});
此结构使用 "control flows" 功能的 "framing" 特性。
我对 selenium-webdriver 命令的执行顺序有点困惑。
以下示例的正确编码是什么。 我想:
- 首先,在文本框中输入文字
- 然后,单击按钮
以下代码是否保证顺序正确?
// Enter the text
driver.findElement(webdriver.By.id('txt'))
.sendKeys('bla bla')
.then(
function() {},
function(err) {
console.log(err);
done(err);
}
);
// Press the button
driver.findElement(webdriver.By.id('btn'))
.click()
.then(
function() {
done();
},
function(err) {
console.log(err);
done(err);
}
);
或者我应该这样做吗?
// Enter the pass
driver.findElement(webdriver.By.id('txt_pass'))
.sendKeys('sifra')
.then(
function() {
// Press the login button
driver.findElement(webdriver.By.id('btn_login'))
.click()
.then(
function() {
done();
},
function(err) {
console.log(err);
done(err);
}
);
},
function(err) {
console.log(err);
done(err);
}
);
如果第二种情况是正确的,当连续需要2个以上的动作时,代码应该怎么写?我会很复杂,必须维护。
更新:
假设现在我想清除在第一个 findElement 中找到的元素 "txt",并在我输入文本之前执行此操作。根据 Louis 的回答,我怀疑它应该是什么像这样:
// Clear the textbox
driver.findElement(webdriver.By.id('txt'))
.clear()
.then(
function() {},
function(err) {
console.log(err);
done(err);
}
);
// Enter the text
driver.findElement(webdriver.By.id('txt'))
.sendKeys('bla bla')
.then(
function() {},
function(err) {
console.log(err);
done(err);
}
);
// go on with the further sequence...
我觉得这不是很好,它太长而且笨拙,尤其是在同一元素上有更多操作的情况下。有没有一种通用的方法可以缩短它,使其更紧凑?
类似链接的东西:
findElement('txt').clear().sendKeys('bla, bla'); // This does not work, as clear is a void
你的第一种方法是正确的。您似乎缺少的信息是 WebDriver 的 JavaScript 实现使用 "promise manager" 为您排序承诺。 这在 "Control Flows" 指南部分。这是一个例子:
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().
withCapabilities(webdriver.Capabilities.chrome()).
build();
// Do not implicitly wait for anything.
driver.manage().timeouts().implicitlyWait(0);
// Set the script wait timeout to 10 seconds.
driver.manage().timeouts().setScriptTimeout(10 * 1000);
driver.get('http://www.example.com');
function err() {
console.log("ERR", arguments);
}
var start = Date.now();
driver.executeAsyncScript(
"var done = arguments[0];" +
"setTimeout(function () { document.body.innerHTML = '<p id=\"foo\"></p>'; done() }, 5000)")
.then(function () {
console.log("created foo!", Date.now() - start);
},
err);
driver.findElement(webdriver.By.tagName("body")).then(function () {
console.log("here", Date.now() - start);
});
driver.findElement(webdriver.By.id("foo")).then(function () {
console.log("found foo!", Date.now() - start);
}, err);
这将向控制台输出以下行,始终以相同的顺序:
created foo! 5639
here 5657
found foo! 5670
数字会有所不同,但它们总是 > 5000,并且彼此非常接近(除非 运行 在超载或慢得离谱的系统上)。首先执行的 executeAsyncScript
是为了说明需要一段时间才能完成的操作 而不是 将允许对同一驱动程序进行后续操作。除了它执行脚本而不是查找元素之外,它与 findElement
没有任何不同:promise 管理器等待直到操作完成,然后才能继续下一个操作,even 如果两个操作没有使用 .then()
.
如果 promise 管理器没有一个接一个地对操作进行排序,那么 .findElement(webdriver.By.tagName("body"))
将在异步脚本完成之前执行,并且它会在 "created foo!"
之前打印 "here"
打印到控制台,因为该页面确实有一个 body
元素。
另外,如果承诺管理器没有一个接一个地对操作进行排序,那么最后一个 .findElement
将无法找到 id
值为 foo
的元素。在脚本的早期,我关闭了隐式等待,因此 findElement
调用肯定不会 等待 等待 foo
出现。
在 种情况下,您更希望像在第二个代码段中那样做,但您没有在问题中包含任何明确的理由应该这样做方式。
此外,如果不是 Selenium 的承诺管理器,那么您 必须 执行类似于您的第二个代码段的操作,因为通常没有任何顺序承诺适合您。
关于您关于如何对 clear
和 sendKeys
进行排序的问题,您可以这样做:
driver.findElement(webdriver.By.id('txt')).then(function (el) {
el.clear();
el.sendKeys('bla bla');
});
此结构使用 "control flows" 功能的 "framing" 特性。