Browser Restart Using Geb & Spock within same test

。_饼干妹妹 提交于 2019-12-12 03:58:04

问题


I would like to be able to restart my browser session mid test using Geb and Spock Framework. I no howto close the browser and update after test compltion etc, but when i close during the test and try and re use the browser object i get a session error thrown by selenium. Below is the base outline i am trying to execute. NB never allows me to navigate to the new StoreHome and if i try and use just Browser i get error thrown.

@Category(High.class)
def "TC1: Verify Browser Restart"() {
    when: "On my StoreFront HP wait until title displayed"
    to StoreHomePage
    waitFor { homepagetitle.displayed }

    then: "Update your site picker"
    mySitePicker.click()
    waitFor { myNewHomePageTitle.displayed }

    when: "Close the browser and insure on restart new page is loaded"
    browser.close()
    browser.quit()

    def nb = new Browser()
    nb.to(NewStoreHomePage)

    then: "Validate on New HP"
    asset myNewHomePageTitle.displayed
}

回答1:


It's as simple as doing the following in your spec:

resetBrowser()
CachingDriverFactory.clearCacheAndQuitDriver()

After that any code that tries to access browser will trigger automatic creation of new WebDriver and Browser instances.




回答2:


This is how you force a new driver:

CachingDriverFactory.clearCache()

I tested it, it works beautifully. This hint can also be found in the Geb manual.


Update 2017-02-07 15:10 CET: Thanks for the follow-up question. Well, my brief answer was made under the assumption that the command is issued at the and of one feature method and the next feature method starts with a new browser session. In order to do this mid-test you would have to create a new WebDriver instance manually and somehow trick Geb into updating its browser session.

Because this is tricky at least and I do not know how to do it, I recommend using two separate feature methods for testing what should be tested before and after quitting the browser. You can share state between them via @Shared members, if necessary. This also had the advantage that if you let Geb create the new WebDriver and browser session for you, everything configured in GebConfig.groovy, such as browser type and capabilities, will automatically be considered. If you would create a driver manually, you would have to parse the Geb config by yourself - ugly!

But the main problem with this approach is: How to assure that the feature methods are executed in the (lexical) order of declaration? Normally tests should be runnable in any order, so you cannot and should not rely on a specific execution order. Spock offers the Stepwise annotation to adress the rare case in which you want to enforce execution order, but this would lead to the same problem as in the mid-test situation because Geb implicitly assumes that it should continue to test in the same session. I.e. we need a trick to enforce lexical execution order without using @Stepwise.

Another problem is that if your spec extends GebReportingSpec because you want to take screenshots, Geb fails to take the last screenshot at the end of the feature method with the browser gone. Now you can configure Geb not to take screenshots if the test succeeds via reportOnTestFailureOnly, but that still leaves us with failed tests. So I added an override for the report method with some additional exception handling.

The full solution looks like this, derived from one of my real-life tests:

package de.scrum_master.tdd

import geb.driver.CachingDriverFactory
import geb.spock.GebReportingSpec
import org.openqa.selenium.Keys
import org.spockframework.runtime.model.FeatureInfo
import spock.lang.Shared

class SampleGebIT extends GebReportingSpec {

  @Override
  void report(String label = "") {
    // GebReportingSpec tries to write a report (screenshot) at the end of each feature
    // method. But because we use 'CachingDriverFactory.clearCacheAndQuitDriver()',
    // there is no valid driver instance anymore from which to get a screenshot. Geb is
    // unprepared for this kind of error, so we handle it gracefully so as to keep the
    // test from failing just because the last screenshot cannot be taken anymore.
    try {
      super.report(label)
    }
    catch (Exception e) {
      System.err.println("Cannot create screenshot: ${e.message}")
    }
  }

  // We cannot use 'specificationContext' directly from 'setupSpec()' because of this
  // compilation error: "Only @Shared and static fields may be accessed from here"
  // Okay then, so use we a @Shared field as a workaround. ;-)
  @Shared
  def currentSpec = specificationContext.currentSpec

  def setupSpec() {
    // Make sure that feature methods are run in declaration order. Normally we could
    // use @Stepwise for this, but because @Stepwise implies staying in the same
    // browser session, it would not work in connection with
    // 'CachingDriverFactory.clearCacheAndQuitDriver()'. This is the workaround for it.
    for (FeatureInfo feature : currentSpec.features)
      feature.executionOrder = feature.declarationOrder
  }

  def "Search web site Scrum-Master.de"() {
    setup:
    def deactivateAutoComplete =
      "document.getElementById('mod_search_searchword')" +
      ".setAttribute('autocomplete', 'off')"
    def regexNumberOfMatches = /Insgesamt wurden ([0-9]+) Ergebnisse gefunden/

    when:
    go "https://scrum-master.de"
    report "welcome page"

    then:
    $("h2").text().startsWith("Herzlich Willkommen bei Scrum-Master.de")

    when:
    js.exec(deactivateAutoComplete)
    $("form").searchword = "Product Owner" + Keys.ENTER

    then:
    waitFor { $("form#searchForm") }

    when:
    report "search results"
    def searchResultSummary = $("form#searchForm").$("table.searchintro").text()
    def numberOfMatches = (searchResultSummary =~ regexNumberOfMatches)[0][1] as int

    then:
    numberOfMatches > 0

    cleanup:
    println "Closing browser and WebDriver"
    CachingDriverFactory.clearCacheAndQuitDriver()
  }

  def "Visit Scrum-Master.de download page"() {
    when:
    go "https://scrum-master.de/Downloads"
    report "download page"

    then:
    $("h2").text().startsWith("Scrum on a Page")
  }
}

BTW, I tested this successfully with several browsers on my Windows 10 machine:

  • HtmlUnit (with activated JavaScript)
  • PhantomJS
  • Chrome
  • Internet Explorer
  • Edge
  • Firefox


来源:https://stackoverflow.com/questions/42069291/browser-restart-using-geb-spock-within-same-test

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!