Bohdan Nesteruk
Bohdan Nesteruk

Reputation: 914

GEB: driver is not set as Browser.driver

I'm writing tests with GEB and Spock (I'm new to both).

Driver is declared in GebConfig (updated - the full config file added):

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")
        }
    }
}

Test example looks like (BaseTest code is added below):

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"
    }
}

And I get the following log sequence:

test started
Created driver
when
then

Created driver
Clean up specification 

So the driver gets created when to LoginPage is called.

Issue: It is not set as Browser driver, so when the browser.quit() is called, a new instance is created and then closed (the first one still is opened).

Questions:

  1. How to set the driver to browser properly to close it then via browser.quit()?

  2. Am I right assuming that if I need to create a driver in setupSpec I can simply call to LoginPage there? Or what is the best way to init the driver in preconditions?

UPDATE:

After some debugging I found out that for some reason, browser gecomes null and is created again in cleanupSpec(). It doesn't matter whether the Spec extends Geb classes of custom base class. This reproduces my issue:

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"
    }
}

This produces the following output:

setupSpec browser: geb.Browser@4beeb0e
setup browser: geb.Browser@4beeb0e
test started


cleanup browser: geb.Browser@4beeb0e
cleanupSpec browser: geb.Browser@5c73f672

The last two rows show that the browser object in cleanupSpec is different from created object in setupSpec.

Upvotes: 0

Views: 1070

Answers (2)

Michael
Michael

Reputation: 2683

I'm not sure, why the browser was closed before your cleanupSpec. Probably some other mechanism already took care of it.

The fact that you are getting a different instance in your cleanupSpec however is simply due to the fact, that getBrowser is implemented as a lazy getter. It creates a new instance if necessary, as you can see in the code.

Generally you don't need to call browser.quit using Geb. Geb takes care of that just fine.

Update

Here is what happens in GebSpec and YourSpec:

  1. GebSpec.setupSpec is triggered ⇒ _browser is null
  2. YourSpec.setupSpec is triggered ⇒ _browser is still null unless you use it here
  3. GebSpec.setup is triggered ⇒ _browser is not changed
  4. YourSpec.setup is triggered ⇒ _browser might be changed
  5. YouSpec's first feature is triggered ⇒ _browser is used, so it won't be null anymore
  6. YourSpec.cleanup is triggered ⇒ _browser is not changed
  7. GebSpec.cleanup is triggered ⇒ _browser is set to null! As you can see in the code, resetBrowser is called unless YourSpec is @Stepwise and that sets _browser to null as you can see here.
  8. YourSpec.cleanupSpec is triggered ⇒ _browser is null unless you use it, so it gets reinitialized
  9. GebSpec.cleanupSpec is triggered ⇒ _browser is still null

Upvotes: 1

Rushby
Rushby

Reputation: 889

This seems strange that you are seeing the browser reinitialise for the cleanup, what you have shown is correct.

For point 1: You are setting it correctly within the gebconfig.

For point 2: You don't need to initialise the browser within the setupSpec(), the config entry is all you need.

The browser should close automatically once all tests are run, UNLESS you have added the following to your gebconfig and set to false:

quitCachedDriverOnShutdown = false 

setupSpec() is called after all methods within the spec have been run. Is what you have shown us the only code within your spec? Is your spec extending GebSpec or GebReportingSpec or a custom base class?

The only other thing i can think is that you have 2 tests in that spec, so you're seeing "Created driver" twice, and the cleanUpSpec() is called after all tests are run so you see that called at the end. If you had called cleanup() it would run between each test.

Upvotes: 0

Related Questions