私はSeleniumを使用していますが、複数のTABSを一度に使用できるかどうか疑問に思っていますか?複数のブラウザインスタンスを使用したくない(つまり、IE pun)の2つのコピー)。ITIS不可能な場合、どのように切り替えるか連続して実行されている個々のタブ?
ありがとう!
新しいウィンドウ/タブを開くリンクがある場合は、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:
同じウィンドウに複数のタブがある場合、ウィンドウハンドルは1つだけです。したがって、ウィンドウハンドルを切り替えると、コントロールは同じタブに保持されます。
この場合、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");
詳細なサンプルコードは次の場所にあります。
http://design-interviews.blogspot.com/2014/11/switching-between-tabs-in-same-browser-window.html
複数のタブを開くには:
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);
}
それらを切り替える:
for (int i = 0; i < driver.WindowHandles.Count; i++)
{
driver.SwitchTo().Window(driver.WindowHandles[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));
最近、簡単なマルチスレッドユーティリティを実装しました。これにより、個別のスレッド上の個別のタブでテストを実行できますWITH JUST ONE WEBDRIVER INSTANCE。 WebDriver
の問題は、一度に1つのタブ(ウィンドウ)しかフォーカスできないことです。したがって、複数のタブでテストを行うには、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)
}
}
複数のウィンドウを同時に実行する場合は、IWebDriverの複数のインスタンスでスレッドを使用します
例:
public void Work()
{
IWebDriver driver = new ChromeDriver("D:\\Drivers");
driver.Navigate().GoToUrl(URL);
\\Do the rest
}
public void Work2()
{
IWebDriver driver = new ChromeDriver("D:\\Drivers");
driver.Navigate().GoToUrl(URL2);
\\Do the rest
}
そして、次のような関数を呼び出します:
Thread thread1 = new Thread(new ThreadStart(Work));
thread1.Start();
Thread thread2 = new Thread(new ThreadStart(Work2));
thread2.Start();