简体   繁体   中英

How do I close() and quit() Selenium driver without affecting other steps in Cucumber and Selenium?

I have two feature files in Cucumber that are linked to corresponding step files. The problem is that when one of the step file finishes execution then it closes all the browser windows (because of driver.quit() ) whereby killing the execution of other step file which hasn't done processing yet.

Here each step file opens a new browser window, executes the tests within it and then closes and quits the browser. Currently I have just two step files but in the future there are going to be many more.

Is there anything in Cucumber that would always get executed after all the steps are executed?

How do I solve this problem?

HelpStep.java

@Ignore
public class HelpStep {

    private WebDriver driver;

    @Before
    public void setup() {
        System.out.println("Into the setup method of HelpStep...");
        this.driver = BrowserConfig.getIEWebDriver();
    }

    @Given("^The user is on the Help page$")
    public void onPage() {
        System.out.println("The user is on the Help page");
    }

    @When("^The user clicks on the links within the Help page$")
    public void clickLinks() {
        System.out.println("The user clicks on the links within the Help page");
    }

    @Then("^The user is navigated to that section$")
    public void validate() {
        System.out.println("The user is navigated to that section");
    }

    @After
    public void cleanUp() {
        System.out.println("Into the cleanUp method of HelpStep...");
        //FOLLOWING METHOD CALL KILLS ALL THE OPEN BROWSERS ALSO :(
        BrowserConfig.releaseResources(this.driver);
    }

}

LinkStatsStep.java

@Ignore
public class LinkStatsStep {

    private WebDriver driver;

    @Before
    public void setup() {
        System.out.println("Into the setup method of LinkStatsStep...");
        this.driver = BrowserConfig.getIEWebDriver();
    }

    @Given("^The user is on the Link Statistics page$")
    public void onPage() {
        System.out.println("The user is on the Link Statistics page");
    }

    @When("^The user does a search$")
    public void clickLinks() {
        System.out.println("The user does a search");
    }

    @Then("^The user is displayed search result$")
    public void validate() {
        System.out.println("The user is displayed search result");
    }

    @After
    public void cleanUp() {
        System.out.println("Into the cleanUp method of LinkStatsStep...");
        BrowserConfig.releaseResources(this.driver);
    }

}

TestRunner.java

@RunWith(Cucumber.class)
@CucumberOptions(
        plugin = {"pretty", "json:target/cucumber-reports/cucumber.json"},
        features = {"src/test/resources/features"})
public class TestRunner extends ApplicationTests {

}

BrowserConfig.java

public class BrowserConfig {

    private static final String IE_DRIVER_EXE = "drivers/IEDriverServer.exe";
    private static final String WEBDRIVER_IE_DRIVER = "webdriver.ie.driver";
    private static final String BASE_URL = "https://www.google.com";

    public static WebDriver getIEWebDriver() {
        String filePath = ClassLoader.getSystemClassLoader().getResource(IE_DRIVER_EXE).getFile();
        System.setProperty(WEBDRIVER_IE_DRIVER, filePath);
        InternetExplorerOptions options = new InternetExplorerOptions().requireWindowFocus();
        options.setCapability(INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
        options.setCapability(ENABLE_ELEMENT_CACHE_CLEANUP, true);
        options.setCapability(IE_ENSURE_CLEAN_SESSION, true);
        options.setCapability(ACCEPT_SSL_CERTS, true);
        options.setCapability("nativeEvents", false);
        options.setCapability(INITIAL_BROWSER_URL, BASE_URL);
        System.out.println("Initializing IE Driver now...........");
        WebDriver driver = new InternetExplorerDriver(options);
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        return driver;
    }

    public static void releaseResources(WebDriver driver) {
        System.out.println("Releasing resources now.....");
        if (null != driver) {
            driver.close();
            driver.quit(); //CLOSES ALL THE OPEN BROWSER SESSIONS LEAVING OTHER STEP EXECUTIONS INCOMPLETE
        }
    }

}

help.feature

Feature: Check that the user is able to navigate to Help page

  Scenario:
    Given The user is on the Help page
    When The user clicks on the links within the Help page
    Then The user is navigated to that section

link-stats.feature

Feature: Check that the user is able to navigate to Link Statistics page

  Scenario:
    Given The user is on the Link Statistics page
    When The user does a search
    Then The user is displayed search result

System.outs

Initializing IE Driver now...........
Listening on port 47613
Into the setup method of LinkStatsStep...
Initializing IE Driver now...........
Listening on port 5009
The user is on the Help page
The user clicks on the links within the Help page
The user is navigated to that section
Into the cleanUp method of HelpStep...
Releasing resources now.....
Into the cleanUp method of LinkStatsStep...
Releasing resources now.....


Into the setup method of HelpStep...
Initializing IE Driver now...........
Listening on port 17291
Into the setup method of LinkStatsStep...
Initializing IE Driver now...........
Listening on port 23793
The user is on the Link Statistics page
The user does a search
The user is displayed search result
Into the cleanUp method of HelpStep...
Releasing resources now.....
Into the cleanUp method of LinkStatsStep...
Releasing resources now.....

Looking at your code it would appear to be correct.

Calling quit should close all open windows associated with that webdriver session. It should not close windows of other webdriver sessions. So I think you are facing a problem in the IEDriverServer .

If this is the case and if you are running your tests in a JVM that shuts down after all tests have been executed. Then as a work around you can use shut down hooks to call quite and close all web driver sessions. For example:

private static final Thread CLOSE_THREAD = new Thread() {
    @Override
    public void run() {
      // Start a new webdriver to call quit on
      // For IE this will terminate all webdriver sessions
      getIEWebDriver().quit();
    }
};

static {
    Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
}

Posted the answer here as this question is more or less similar earlier one. https://stackoverflow.com/a/55836832/2325154

It is because driver management not done properly. I would suggest to use qaf which does driver and resource management. With QAF your step file will look like below:

public class HelpStep {
    //setup or tear-down not required here...

    @Given("^The user is on the Help page$")
    public void onPage() {
       //you can access driver any where like below:
       //WebDriver driver = new WebDriverTestBase().getDriver();
        System.out.println("The user is on the Help page");
    }

    @When("^The user clicks on the links within the Help page$")
    public void clickLinks() {
        System.out.println("The user clicks on the links within the Help page");
    }

    @Then("^The user is navigated to that section$")
    public void validate() {
        System.out.println("The user is navigated to that section");
    }
}

To access driver object any where in the code you can get it from test base.

WebDriver driver = new WebDriverTestBase().getDriver();

Below are examples of interacting with element anywhere in the code:

  • Using findBy
    • driver.findElement("name=q").click();
  • Using element factory
      import static com.qmetry.qaf.automation.ui.webdriver.ElementFactory.$;
      ...
      $("name=q").click();
  • Using inbuilt step library
      import static com.qmetry.qaf.automation.step.CommonStep.*;
      ...
      click("name=q");

in example above name=q is element locator using name as locator strategy, which will automatically converted to By.name .

LinkStatsStep

import static com.qmetry.qaf.automation.step.CommonStep.*;
...

public class LinkStatsStep {


    @Given("^The user is on the Link Statistics page$")
    public void onPage() {
        get("/");
    }

    @When("^The user does a search$")
    public void clickLinks() {
        System.out.println("The user does a search");
        click("elementlocator");
        //$("elementlocator").click();
    }

    @Then("^The user is displayed search result$")
    public void validate() {
        verifyLinkWithPartialTextPresent("link text");
        //$("partialLink=link text").verifyPresent();
    }

}

Your gherkin file will remain same. To run your gherkin file use GherkinScenarioFactory

You can specify browser to use using driver.name property . You don't need to write code for creating or tearing down driver. You can set behavior of driver session by using selenium.singletone property.

#this will tear down driver after each testcase/scenario
selenium.singletone=method
#this will tear down driver after each xml test node in configuration file
selenium.singletone=test
#this will tear down driver after each xml test node in configuration file and will reuse same driver session for testcases/scenario configured under same xml test node.
selenium.singletone=test
#this will tear down driver after each xml suite node in configuration file.
selenium.singletone=suite

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM