25

私は Selenium を使用していますが、一度に複数の TABS を使用できるかどうか疑問に思っていますか? 複数のブラウザ インスタンスを使用したくありません (つまり、IE しゃれの 2 つのコピー)。それが不可能な場合、順番に実行されている個々のタブを切り替えるにはどうすればよいでしょうか?

ありがとう!

4

7 に答える 7

42

新しいウィンドウ/タブを開くリンクがある場合は、使用できますdriver.switchTo().window();

ただし、複数のウィンドウで何かを実行したい場合は、webdriver の複数のインスタンスを用意することをお勧めします。管理がはるかに簡単で、サポートされています (新しいウィンドウを開くホットキーを押すなど、新しいタブ/ウィンドウを開くための回避策がありますが、サポートされていません)。

複数のスレッドをすべて同じドライバー インスタンスで動作させたいが、異なるタブを使用したい場合、それは不可能です。

于 2013-08-09T15:46:46.400 に答える
15

複数のブラウザー インスタンスがなくても、個々のタブを切り替えることができます。
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にあります。

于 2015-06-17T05:36:09.257 に答える
1

私は最近、別のスレッドの別のタブでテストを実行できるシンプルなマルチスレッド ユーティリティを実装しました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)
    }

}
于 2019-05-08T21:14:11.247 に答える
1

これにより、 seleniumnodejsを使用している場合の問題が解決されます。

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);
  })
于 2019-12-17T12:28:41.590 に答える