GEB:驱动程序未设置为 Browser.driver
GEB: driver is not set as Browser.driver
我正在使用 GEB 和 Spock 编写测试(我对两者都不熟悉)。
驱动程序在 GebConfig 中声明(已更新 - 添加了完整的配置文件):
import geb.report.ReportState
import geb.report.Reporter
import geb.report.ReportingListener
import io.github.bonigarcia.wdm.WebDriverManager
import io.qameta.allure.Allure
import org.openqa.selenium.Dimension
import org.openqa.selenium.Point
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.firefox.FirefoxDriver
import org.openqa.selenium.firefox.FirefoxOptions
import org.openqa.selenium.firefox.FirefoxProfile
import org.slf4j.LoggerFactory
import utils.Configuration
def logger = LoggerFactory.getLogger(this.class)
baseUrl = "${Configuration.getStringProperty("BASE_URL")}/${Configuration.getStringProperty("CONTEXT_PATH")}"
baseNavigatorWaiting = true
autoClearCookies = false
cacheDriver = false
reportsDir = 'build/test-reports'
driver = {
WebDriver dr
switch (Configuration.getStringProperty("BROWSER_NAME", "chrome").trim().toLowerCase()) {
case "firefox":
case "ff":
dr = new FirefoxDriver(setUpFirefoxOptions())
break
case "google chrome":
case "chrome":
default:
dr = new ChromeDriver(setUpGoogleChromeOptions())
}
if (Configuration.getBooleanProperty("SET_DRIVER_POSITION", false)) {
dr.manage().window().setPosition(new Point(
Configuration.getIntProperty("BROWSER_X_POS", 0),
Configuration.getIntProperty("BROWSER_Y_POS", 0)))
dr.manage().window().setSize(new Dimension(
Configuration.getIntProperty("BROWSER_WIDTH", 1600),
Configuration.getIntProperty("BROWSER_HEIGHT", 900)));
} else {
dr.manage().window().maximize()
}
return dr
}
static ChromeOptions setUpGoogleChromeOptions() {
WebDriverManager.chromedriver().setup()
ChromeOptions options = new ChromeOptions()
String args = Configuration.getStringProperty("BROWSER_ARGS")
if (args) {
Arrays.stream(args.split("\s")).each { options.addArguments(it) }
}
return options
}
static FirefoxOptions setUpFirefoxOptions() {
WebDriverManager.firefoxdriver().setup()
FirefoxOptions options = new FirefoxOptions()
FirefoxProfile profile = new FirefoxProfile()
profile.setPreference("network.automatic-ntlm-auth.trusted-uris", "http://,https://")
options.setProfile(profile).setLegacy(false)
return options
}
reportingListener = new ReportingListener() {
void onReport(Reporter reporter, ReportState reportState, List<File> reportFiles) {
def fileGroups = reportFiles.groupBy { it.name.split("\.")[-1] }
fileGroups['png']?.each {
Allure.addAttachment(it.name, "image/png", new FileInputStream(it), "png")
}
}
}
测试示例如下(下面添加了BaseTest代码):
class SimulationsRunningSpec extends BaseTest {
def "My great test"() {
println("test started")
setup:
to LoginPage
when:
println("when")
then:
println("then")
}
def cleanupSpec() {
browser.quit()
println "Clean up specification"
}
}
我得到以下日志序列:
test started
Created driver
when
then
Created driver
Clean up specification
因此在调用 to LoginPage
时会创建驱动程序。
问题:
它没有设置为浏览器驱动程序,所以当 browser.quit()
被调用时,一个新的实例被创建然后关闭(第一个仍然是打开的)。
问题:
如何正确设置驱动到浏览器然后通过browser.quit()
关闭浏览器?
如果我需要在 setupSpec 中创建驱动程序,我可以简单地调用 to LoginPage
吗?或者在前提条件下初始化驱动程序的最佳方法是什么?
更新:
经过一些调试后我发现由于某种原因,浏览器会出现 null
并在 cleanupSpec()
中重新创建。规范是否扩展自定义基础 class 的 Geb class 并不重要。这重现了我的问题:
class TestSpec extends GebReportingSpec {
def setupSpec() {
to Page
println "setupSpec browser: $browser"
}
def setup(){
println "setup browser: $browser"
}
def "My first test"() {
println("test started")
when:
println ''
then:
println ''
}
def cleanup() {
println "cleanup browser: $browser"
}
def cleanupSpec() {
println "cleanupSpec browser: $browser"
}
}
这会产生以下输出:
setupSpec browser: geb.Browser@4beeb0e
setup browser: geb.Browser@4beeb0e
test started
cleanup browser: geb.Browser@4beeb0e
cleanupSpec browser: geb.Browser@5c73f672
最后两行显示 cleanupSpec
中的 browser
对象与 setupSpec
中创建的对象不同。
您看到浏览器重新初始化以进行清理,这似乎很奇怪,您所显示的是正确的。
对于第 1 点:您在 gebconfig 中正确设置了它。
对于第 2 点:您不需要在 setupSpec() 中初始化浏览器,配置条目就是您所需要的。
一旦所有测试完成 运行,浏览器应该会自动关闭,除非您已将以下内容添加到 gebconfig 并设置为 false:
quitCachedDriverOnShutdown = false
setupSpec() 在规范中的所有方法都被 运行 之后调用。您向我们展示的是您规范中的唯一代码吗?您的规范是扩展 GebSpec 或 GebReportingSpec 还是自定义基础 class?
我唯一能想到的是你在那个规范中有 2 个测试,所以你看到 "Created driver" 两次,并且在所有测试都是 运行 之后调用 cleanUpSpec()所以你看到最后调用了。如果您调用了 cleanup() 它会在每次测试之间 运行。
我不确定为什么浏览器在 cleanupSpec
之前关闭。可能其他机制已经解决了它。
然而,您在 cleanupSpec
中获得不同实例的事实仅仅是因为 getBrowser
是作为惰性 getter 实现的。如有必要,它会创建一个新实例,如您在 code.
中所见
通常您不需要使用 Geb 调用 browser.quit
。 Geb 处理得很好。
更新
这是 GebSpec
和 YourSpec
中发生的事情:
GebSpec.setupSpec
被触发 ⇒ _browser
是 null
YourSpec.setupSpec
被触发 ⇒ _browser
仍然是 null
除非你在这里使用它
GebSpec.setup
被触发⇒_browser
未改变
YourSpec.setup
已触发 ⇒ _browser
可能会更改
YouSpec
的第一个特征被触发⇒ _browser
被使用,所以它不会是null
了
YourSpec.cleanup
被触发⇒_browser
没有改变
GebSpec.cleanup
被触发 ⇒ _browser
被设置为 null
! 正如你在 code, resetBrowser
is called unless YourSpec
is @Stepwise
and that sets _browser
to null as you can see here 中看到的那样。 =68=]
YourSpec.cleanupSpec
被触发 ⇒ _browser
是 null
除非你使用它,所以它会被重新初始化
GebSpec.cleanupSpec
被触发 ⇒ _browser
仍然是 null
我正在使用 GEB 和 Spock 编写测试(我对两者都不熟悉)。
驱动程序在 GebConfig 中声明(已更新 - 添加了完整的配置文件):
import geb.report.ReportState
import geb.report.Reporter
import geb.report.ReportingListener
import io.github.bonigarcia.wdm.WebDriverManager
import io.qameta.allure.Allure
import org.openqa.selenium.Dimension
import org.openqa.selenium.Point
import org.openqa.selenium.WebDriver
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.firefox.FirefoxDriver
import org.openqa.selenium.firefox.FirefoxOptions
import org.openqa.selenium.firefox.FirefoxProfile
import org.slf4j.LoggerFactory
import utils.Configuration
def logger = LoggerFactory.getLogger(this.class)
baseUrl = "${Configuration.getStringProperty("BASE_URL")}/${Configuration.getStringProperty("CONTEXT_PATH")}"
baseNavigatorWaiting = true
autoClearCookies = false
cacheDriver = false
reportsDir = 'build/test-reports'
driver = {
WebDriver dr
switch (Configuration.getStringProperty("BROWSER_NAME", "chrome").trim().toLowerCase()) {
case "firefox":
case "ff":
dr = new FirefoxDriver(setUpFirefoxOptions())
break
case "google chrome":
case "chrome":
default:
dr = new ChromeDriver(setUpGoogleChromeOptions())
}
if (Configuration.getBooleanProperty("SET_DRIVER_POSITION", false)) {
dr.manage().window().setPosition(new Point(
Configuration.getIntProperty("BROWSER_X_POS", 0),
Configuration.getIntProperty("BROWSER_Y_POS", 0)))
dr.manage().window().setSize(new Dimension(
Configuration.getIntProperty("BROWSER_WIDTH", 1600),
Configuration.getIntProperty("BROWSER_HEIGHT", 900)));
} else {
dr.manage().window().maximize()
}
return dr
}
static ChromeOptions setUpGoogleChromeOptions() {
WebDriverManager.chromedriver().setup()
ChromeOptions options = new ChromeOptions()
String args = Configuration.getStringProperty("BROWSER_ARGS")
if (args) {
Arrays.stream(args.split("\s")).each { options.addArguments(it) }
}
return options
}
static FirefoxOptions setUpFirefoxOptions() {
WebDriverManager.firefoxdriver().setup()
FirefoxOptions options = new FirefoxOptions()
FirefoxProfile profile = new FirefoxProfile()
profile.setPreference("network.automatic-ntlm-auth.trusted-uris", "http://,https://")
options.setProfile(profile).setLegacy(false)
return options
}
reportingListener = new ReportingListener() {
void onReport(Reporter reporter, ReportState reportState, List<File> reportFiles) {
def fileGroups = reportFiles.groupBy { it.name.split("\.")[-1] }
fileGroups['png']?.each {
Allure.addAttachment(it.name, "image/png", new FileInputStream(it), "png")
}
}
}
测试示例如下(下面添加了BaseTest代码):
class SimulationsRunningSpec extends BaseTest {
def "My great test"() {
println("test started")
setup:
to LoginPage
when:
println("when")
then:
println("then")
}
def cleanupSpec() {
browser.quit()
println "Clean up specification"
}
}
我得到以下日志序列:
test started
Created driver
when
then
Created driver
Clean up specification
因此在调用 to LoginPage
时会创建驱动程序。
问题:
它没有设置为浏览器驱动程序,所以当 browser.quit()
被调用时,一个新的实例被创建然后关闭(第一个仍然是打开的)。
问题:
如何正确设置驱动到浏览器然后通过
browser.quit()
关闭浏览器?如果我需要在 setupSpec 中创建驱动程序,我可以简单地调用
to LoginPage
吗?或者在前提条件下初始化驱动程序的最佳方法是什么?
更新:
经过一些调试后我发现由于某种原因,浏览器会出现 null
并在 cleanupSpec()
中重新创建。规范是否扩展自定义基础 class 的 Geb class 并不重要。这重现了我的问题:
class TestSpec extends GebReportingSpec {
def setupSpec() {
to Page
println "setupSpec browser: $browser"
}
def setup(){
println "setup browser: $browser"
}
def "My first test"() {
println("test started")
when:
println ''
then:
println ''
}
def cleanup() {
println "cleanup browser: $browser"
}
def cleanupSpec() {
println "cleanupSpec browser: $browser"
}
}
这会产生以下输出:
setupSpec browser: geb.Browser@4beeb0e
setup browser: geb.Browser@4beeb0e
test started
cleanup browser: geb.Browser@4beeb0e
cleanupSpec browser: geb.Browser@5c73f672
最后两行显示 cleanupSpec
中的 browser
对象与 setupSpec
中创建的对象不同。
您看到浏览器重新初始化以进行清理,这似乎很奇怪,您所显示的是正确的。
对于第 1 点:您在 gebconfig 中正确设置了它。
对于第 2 点:您不需要在 setupSpec() 中初始化浏览器,配置条目就是您所需要的。
一旦所有测试完成 运行,浏览器应该会自动关闭,除非您已将以下内容添加到 gebconfig 并设置为 false:
quitCachedDriverOnShutdown = false
setupSpec() 在规范中的所有方法都被 运行 之后调用。您向我们展示的是您规范中的唯一代码吗?您的规范是扩展 GebSpec 或 GebReportingSpec 还是自定义基础 class?
我唯一能想到的是你在那个规范中有 2 个测试,所以你看到 "Created driver" 两次,并且在所有测试都是 运行 之后调用 cleanUpSpec()所以你看到最后调用了。如果您调用了 cleanup() 它会在每次测试之间 运行。
我不确定为什么浏览器在 cleanupSpec
之前关闭。可能其他机制已经解决了它。
然而,您在 cleanupSpec
中获得不同实例的事实仅仅是因为 getBrowser
是作为惰性 getter 实现的。如有必要,它会创建一个新实例,如您在 code.
通常您不需要使用 Geb 调用 browser.quit
。 Geb 处理得很好。
更新
这是 GebSpec
和 YourSpec
中发生的事情:
GebSpec.setupSpec
被触发 ⇒_browser
是null
YourSpec.setupSpec
被触发 ⇒_browser
仍然是null
除非你在这里使用它GebSpec.setup
被触发⇒_browser
未改变YourSpec.setup
已触发 ⇒_browser
可能会更改YouSpec
的第一个特征被触发⇒_browser
被使用,所以它不会是null
了YourSpec.cleanup
被触发⇒_browser
没有改变GebSpec.cleanup
被触发 ⇒_browser
被设置为null
! 正如你在 code,resetBrowser
is called unlessYourSpec
is@Stepwise
and that sets_browser
to null as you can see here 中看到的那样。 =68=]YourSpec.cleanupSpec
被触发 ⇒_browser
是null
除非你使用它,所以它会被重新初始化GebSpec.cleanupSpec
被触发 ⇒_browser
仍然是null