Blog

selenium で処理を待つときは WebDriverWait を使う

kweb のテストケースが Awaitility 使ってたのでそれをそれを参考にテストを書いていたのだが問題が発生した。 https://github.com/kwebio/kweb-core/blob/master/src/test/kotlin/kweb/InputCheckedTest.kt#L49

        driver.get("http://localhost:$port/")

        val createLink = driver.findElement(By.className("createLink"))
        createLink.click()

        await().untilAsserted {
            URI(driver.currentUrl).path shouldBe "/create"
        }

例えばこんなふうにかいたら以下のようなエラーが発生する。selenium のインスタンスを生成したスレッド以外から selenium の情報を取ろうとしたらエラーになるようだ。

Thread safety error; this instance of WebDriver was constructed on thread Test worker (id 1) and is being accessed by thread awaitility-thread (id 92)This is not permitted and *will* cause undefined behaviour
Build info: version: '4.6.0', revision: '79f1c02ae20'
System info: os.name: 'Mac OS X', os.arch: 'aarch64', os.version: '12.6', java.version: '17.0.2'
Driver info: driver.version: unknown
org.openqa.selenium.WebDriverException: Thread safety error; this instance of WebDriver was constructed on thread Test worker (id 1) and is being accessed by thread awaitility-thread (id 92)This is not permitted and *will* cause undefined behaviour
Build info: version: '4.6.0', revision: '79f1c02ae20'
System info: os.name: 'Mac OS X', os.arch: 'aarch64', os.version: '12.6', java.version: '17.0.2'
Driver info: driver.version: unknown
	at app//org.openqa.selenium.support.ThreadGuard$WebDriverInvocationHandler.invoke(ThreadGuard.java:88)
	at app/jdk.proxy3/jdk.proxy3.$Proxy28.getCurrentUrl(Unknown Source)
	at app//InputCheckedTest.checkBeforeAndAfterClick$lambda$0(MyTest.kt:55)
	at app//org.awaitility.core.AssertionCondition.lambda$new$0(AssertionCondition.java:53)
	at app//org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:248)
	at app//org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:235)
	at [email protected]/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at [email protected]/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at [email protected]/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at [email protected]/java.lang.Thread.run(Thread.java:833)

2022-11-12 09:15:39.580 [Test worker] INFO  kweb.Kweb - Shutting down Kweb
2022-11-12 09:15:39.586 [Test worker] INFO  o.e.jetty.server.AbstractConnector - Stopped ServerConnector@4f824872{HTTP/1.1, (http/1.1, h2c)}{0.0.0.0:7660}

InputCheckedTest > checkBeforeAndAfterClick() FAILED

ということで、調べていたら以下のような情報を得た。 https://note.com/shift_tech/n/n6983acabb51a

というわけで以下のように書いたら、問題が解決した。

        val wait = WebDriverWait(driver, Duration.ofSeconds(5))
        wait.until {
            URI(driver.currentUrl).path == "/create"
        }
       URI(driver.currentUrl).path shouldBe "/create"