Selenium一次创建多个选项卡
我正在使用Selenium,我想知道是否可以同时使用多个选项卡?我不想使用多个浏览器实例(例如,IE pun的两个副本)。如果这是不可能的,人们将如何在连续运行的各个选项卡之间进行切换Selenium一次创建多个选项卡,selenium,tabs,automated-tests,multiple-instances,Selenium,Tabs,Automated Tests,Multiple Instances,我正在使用Selenium,我想知道是否可以同时使用多个选项卡?我不想使用多个浏览器实例(例如,IE pun的两个副本)。如果这是不可能的,人们将如何在连续运行的各个选项卡之间进行切换 谢谢 如果有打开新窗口/选项卡的链接,则可以使用driver.switchTo().window() 但是,如果您想在多个窗口上运行某些东西,那么我建议使用多个webdriver实例。它更易于管理,并且受支持(在打开新选项卡/窗口时有一些变通方法,例如按热键打开新窗口,但不受支持) 如果希望多个线程都作用于同一个
谢谢 如果有打开新窗口/选项卡的链接,则可以使用
driver.switchTo().window()代码>
但是,如果您想在多个窗口上运行某些东西,那么我建议使用多个webdriver实例。它更易于管理,并且受支持(在打开新选项卡/窗口时有一些变通方法,例如按热键打开新窗口,但不受支持)
如果希望多个线程都作用于同一个驱动程序实例,但作用于不同的选项卡,则这是不可能的。可以在单个选项卡之间切换,而不需要多个浏览器实例。
web驱动程序处理不同窗口和不同选项卡的方式有所不同。
案例1:
如果有多个窗口,则以下代码可以提供帮助:
//Get the current window handle
String windowHandle = driver.getWindowHandle();
//Get the list of window handles
ArrayList tabs = new ArrayList (driver.getWindowHandles());
System.out.println(tabs.size());
//Use the list of window handles to switch between windows
driver.switchTo().window(tabs.get(0));
//Switch back to original window
driver.switchTo().window(mainWindowHandle);
案例2:
如果同一窗口中有多个选项卡,则只有一个窗口句柄。因此,在窗口句柄之间切换会使控件保持在同一选项卡中。
在这种情况下,使用Ctrl+\t(Ctrl+tab)在选项卡之间切换更有用。
//Open a new tab using Ctrl + t
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"t");
//Switch between tabs using Ctrl + \t
driver.findElement(By.cssSelector("body")).sendKeys(Keys.CONTROL +"\t");
详细的示例代码可在此处找到:
如果您希望同时运行多个wındows,请对IWebDriver的多个实例使用线程
例:
并按如下方式调用函数:
Thread thread1 = new Thread(new ThreadStart(Work));
thread1.Start();
Thread thread2 = new Thread(new ThreadStart(Work2));
thread2.Start();
要打开多个选项卡,请执行以下操作:
driver = new ChromeDriver();
IJavaScriptExecutor jscript = driver as IJavaScriptExecutor;
for (int i = 0; i < 10; i++)
{
driver.Navigate().GoToUrl(this.baseURL);
jscript.ExecuteScript("window.open('{0}', '_blank');", this.baseURL);
}
driver=newchromedriver();
IJavaScriptExecutor jscript=作为IJavaScriptExecutor的驱动程序;
对于(int i=0;i<10;i++)
{
driver.Navigate().gotour(this.baseURL);
jscript.ExecuteScript(“window.open(“{0}”,“_blank”);”,this.baseURL);
}
在它们之间切换:
for (int i = 0; i < driver.WindowHandles.Count; i++)
{
driver.SwitchTo().Window(driver.WindowHandles[i])]);
}
for(int i=0;i
尝试以下代码
String oldTab = driver.getWindowHandle();
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
ArrayList<String> newTab = new ArrayList<String>(driver.getWindowHandles());
newTab.remove(oldTab);
driver.switchTo().window(newTab.get(0));
String oldTab=driver.getWindowHandle();
driver.manage().timeouts().implicitlyWait(1,TimeUnit.SECONDS);
ArrayList newTab=新的ArrayList(driver.getWindowHandles());
新选项卡。移除(旧选项卡);
driver.switchTo().window(newTab.get(0));
我最近实现了一个简单的多线程实用程序,它允许只使用一个WEBDRIVER实例在不同线程的不同选项卡上运行测试。WebDriver
的问题是,它一次只能聚焦一个选项卡(窗口)。因此,要在多个选项卡中进行测试,WebDriver
必须分别关注每个选项卡。我确信我的实现并不完美,但这里是(Kotlin中的实现):
用法:
fun test() {
val results = ParallelNavigator(webDriver,
listOf(
::test1,
::test2,
::test3
)
).start()
println(results)
// Output: [Success, Failure: java.lang.RuntimeException: Some error, Success]
}
fun test1(pn: ParallelNavigator) {
/* ... open url, find elements etc. so stuff */
pn.resumeNext() // transfer flow to another unfinished thread (test2 if not finished)
/* ... do more stuff */
pn.resumeNext() // again transfer flow to another thread
}
fun test2(pn: ParallelNavigator) { /* ... */ }
fun test3(pn: ParallelNavigator) { /* ... */ }
实施:
import org.openqa.selenium.JavascriptExecutor
import org.openqa.selenium.WebDriver
import org.openqa.selenium.support.ui.WebDriverWait
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.thread
import kotlin.concurrent.withLock
class ParallelNavigator(private val webDriver: WebDriver, executions: List<(ParallelNavigator) -> Unit>) {
private val _executions: List<TabExecution> = executions.map { TabExecution(it) }
private var currentExecutionIndex: Int = -1
fun start(): List<Result> {
createTabs()
return runInternal()
}
fun resumeNext() {
if (_executions.isEmpty()) {
throw RuntimeException("No executions provided.")
}
val currentExecution: TabExecution? = if (currentExecutionIndex != -1) {
_executions[currentExecutionIndex]
} else null
val unfinished = _executions.filter { !it.finished }
if(unfinished.isEmpty()) {
return
}
val nextExecutionIndex = if (currentExecutionIndex >= unfinished.lastIndex || currentExecutionIndex <= -1) {
0
} else {
currentExecutionIndex + 1
}
val nextExecution = unfinished[nextExecutionIndex]
currentExecutionIndex = nextExecutionIndex
webDriver.switchTo().window(nextExecution.windowHandle)
nextExecution.lock.withLock {
nextExecution.condition.signal()
}
currentExecution?.lock?.withLock {
if (!currentExecution.finished) {
currentExecution.condition.await()
}
}
}
sealed class Result {
class Success : Result() {
override fun toString(): String {
return "Success"
}
}
class Failure(val ex: Throwable) : Result() {
override fun toString(): String {
return "Failure: ${ex.javaClass.name}: ${ex.message}"
}
}
class Unfinished : Result() {
override fun toString(): String {
return "Unfinished"
}
}
}
data class TabExecution(
val test: (ParallelNavigator) -> Unit,
val lock: ReentrantLock = ReentrantLock(),
var finished: Boolean = false
) {
lateinit var windowHandle: String
lateinit var condition: Condition
lateinit var thread: Thread
}
private fun createTabs() = with(webDriver) {
navigate().to("about:blank")
val homeWindowHandle = windowHandle
for (execution in _executions) {
execution.windowHandle = openNewTab()
}
webDriver.switchTo().window(homeWindowHandle)
}
private fun runInternal(): List<Result> {
val results = _executions.map { Result.Unfinished() as Result }.toMutableList()
for (index in _executions.indices) {
val execution = _executions[index]
val condition = execution.lock.newCondition()
execution.condition = condition
execution.thread = thread(start = false) {
execution.lock.withLock {
condition.await()
try {
execution.test(this)
results[index] = Result.Success()
} catch (ex: Throwable) {
ex.printStackTrace()
results[index] = Result.Failure(ex)
}
execution.finished = true
currentExecutionIndex--
resumeNext()
}
}
execution.thread.start()
}
resumeNext() // run first execution
for (execution in _executions) {
execution.thread.join()
}
return results
}
fun waitForNewTabToOpen(oldWindowHandles: Set<String>) = with(webDriver) {
waitForNewTabToOpen(oldWindowHandles, 10)
}
fun waitForNewTabToOpen(oldWindowHandles: Set<String>, seconds: Int) = with(webDriver) {
WebDriverWait(webDriver, seconds.toLong()).until<Boolean> { WebDriver -> availableWindowHandles().size > oldWindowHandles.size }
}
fun availableWindowHandles(): Set<String> = with(webDriver) {
return webDriver.getWindowHandles()
}
private fun getNewTabHandle(oldWindowHandles: Set<String>): String = with(webDriver) {
waitForNewTabToOpen(oldWindowHandles)
val newWindowHandles = availableWindowHandles().toMutableSet()
newWindowHandles.removeAll(oldWindowHandles)
return newWindowHandles.iterator().next()
}
fun openNewTab(): String = with(webDriver) {
val oldHandles = availableWindowHandles()
(webDriver as JavascriptExecutor).executeScript("Object.assign(document.createElement('a'), { target: '_blank', href: 'about:blank'}).click();")
waitForNewTabToOpen(oldHandles)
return getNewTabHandle(oldHandles)
}
}
import org.openqa.selenium.JavascriptExecutor
导入org.openqa.selenium.WebDriver
导入org.openqa.selenium.support.ui.WebDriverWait
导入java.util.concurrent.locks.Condition
导入java.util.concurrent.locks.ReentrantLock
导入kotlin.concurrent.thread
导入kotlin.concurrent.withLock
类ParallelNavigator(私有val webDriver:webDriver,执行:列表单元>){
private val_executions:List=executions.map{TabExecution(it)}
私有变量currentExecutionIndex:Int=-1
乐趣开始():列表{
createTabs()
返回runInternal()
}
下一步{
if(_executions.isEmpty()){
抛出RuntimeException(“未提供执行”)
}
val currentExecution:TabExecution?=if(currentExecutionIndex!=-1){
_执行[currentExecutionIndex]
}否则无效
val unfinished=_executions.filter{!it.finished}
if(unfinished.isEmpty()){
返回
}
val nextExecutionIndex=if(currentExecutionIndex>=unfinished.lastIndex | | currentExecutionIndex单元,
val lock:ReentrantLock=ReentrantLock(),
var finished:Boolean=false
) {
lateinit变量windowHandle:字符串
lateinit变量条件:条件
lateinit变量线程:线程
}
private fun createTabs()=与(webDriver){
导航()。到(“关于:空白”)
val homeWindowHandle=windowHandle
用于(在执行中执行){
execution.windowHandle=openNewTab()
}
webDriver.switchTo().window(homeWindowHandle)
}
private fun runInternal():列表{
val results=_executions.map{Result.Unfinished()as Result}.toMutableList()
for(索引在_.index中){
val执行=_执行[索引]
val condition=execution.lock.newCondition()
execution.condition=条件
execution.thread=thread(start=false){
执行锁{
条件等待
试一试{
执行。测试(本)
结果[索引]=结果.成功()
}捕获(例如:可丢弃){
例如printStackTrace()
结果[索引]=结果失败(ex)
}
execution.finished=true
当前执行索引--
resumeNext()
}
}
execution.thread.start()
}
resumeNext()//运行第一次执行
用于(在执行中执行){
execution.thread.join()
}
返回结果
}
趣味waitForNewTabToOpen(旧窗口句柄:设置)=带(webDriver){
waitForNewTabToOpen(旧窗口句柄,10)
}
趣味waitForNewTabToOpen(旧窗口句柄:设置,秒数:Int)=带(webDriver){
WebDriverWait(webDriver,seconds.toLong())。直到{webDriver->availableWind
import org.openqa.selenium.JavascriptExecutor
import org.openqa.selenium.WebDriver
import org.openqa.selenium.support.ui.WebDriverWait
import java.util.concurrent.locks.Condition
import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.thread
import kotlin.concurrent.withLock
class ParallelNavigator(private val webDriver: WebDriver, executions: List<(ParallelNavigator) -> Unit>) {
private val _executions: List<TabExecution> = executions.map { TabExecution(it) }
private var currentExecutionIndex: Int = -1
fun start(): List<Result> {
createTabs()
return runInternal()
}
fun resumeNext() {
if (_executions.isEmpty()) {
throw RuntimeException("No executions provided.")
}
val currentExecution: TabExecution? = if (currentExecutionIndex != -1) {
_executions[currentExecutionIndex]
} else null
val unfinished = _executions.filter { !it.finished }
if(unfinished.isEmpty()) {
return
}
val nextExecutionIndex = if (currentExecutionIndex >= unfinished.lastIndex || currentExecutionIndex <= -1) {
0
} else {
currentExecutionIndex + 1
}
val nextExecution = unfinished[nextExecutionIndex]
currentExecutionIndex = nextExecutionIndex
webDriver.switchTo().window(nextExecution.windowHandle)
nextExecution.lock.withLock {
nextExecution.condition.signal()
}
currentExecution?.lock?.withLock {
if (!currentExecution.finished) {
currentExecution.condition.await()
}
}
}
sealed class Result {
class Success : Result() {
override fun toString(): String {
return "Success"
}
}
class Failure(val ex: Throwable) : Result() {
override fun toString(): String {
return "Failure: ${ex.javaClass.name}: ${ex.message}"
}
}
class Unfinished : Result() {
override fun toString(): String {
return "Unfinished"
}
}
}
data class TabExecution(
val test: (ParallelNavigator) -> Unit,
val lock: ReentrantLock = ReentrantLock(),
var finished: Boolean = false
) {
lateinit var windowHandle: String
lateinit var condition: Condition
lateinit var thread: Thread
}
private fun createTabs() = with(webDriver) {
navigate().to("about:blank")
val homeWindowHandle = windowHandle
for (execution in _executions) {
execution.windowHandle = openNewTab()
}
webDriver.switchTo().window(homeWindowHandle)
}
private fun runInternal(): List<Result> {
val results = _executions.map { Result.Unfinished() as Result }.toMutableList()
for (index in _executions.indices) {
val execution = _executions[index]
val condition = execution.lock.newCondition()
execution.condition = condition
execution.thread = thread(start = false) {
execution.lock.withLock {
condition.await()
try {
execution.test(this)
results[index] = Result.Success()
} catch (ex: Throwable) {
ex.printStackTrace()
results[index] = Result.Failure(ex)
}
execution.finished = true
currentExecutionIndex--
resumeNext()
}
}
execution.thread.start()
}
resumeNext() // run first execution
for (execution in _executions) {
execution.thread.join()
}
return results
}
fun waitForNewTabToOpen(oldWindowHandles: Set<String>) = with(webDriver) {
waitForNewTabToOpen(oldWindowHandles, 10)
}
fun waitForNewTabToOpen(oldWindowHandles: Set<String>, seconds: Int) = with(webDriver) {
WebDriverWait(webDriver, seconds.toLong()).until<Boolean> { WebDriver -> availableWindowHandles().size > oldWindowHandles.size }
}
fun availableWindowHandles(): Set<String> = with(webDriver) {
return webDriver.getWindowHandles()
}
private fun getNewTabHandle(oldWindowHandles: Set<String>): String = with(webDriver) {
waitForNewTabToOpen(oldWindowHandles)
val newWindowHandles = availableWindowHandles().toMutableSet()
newWindowHandles.removeAll(oldWindowHandles)
return newWindowHandles.iterator().next()
}
fun openNewTab(): String = with(webDriver) {
val oldHandles = availableWindowHandles()
(webDriver as JavascriptExecutor).executeScript("Object.assign(document.createElement('a'), { target: '_blank', href: 'about:blank'}).click();")
waitForNewTabToOpen(oldHandles)
return getNewTabHandle(oldHandles)
}
}
driver.get('https://www.google.com/')
.then(_ =>
driver.findElement(webdriver.By.tagName('body'))
)
.then(bodyElement => {
bodyElement.sendKeys(webdriver.Key.chord(webdriver.Key.CONTROL, 't'))
})
.catch(err => {
console.log(err);
})