本文介绍了Cucumber spring WebDriver中的设计问题在@After方法中退出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在尝试使用 cucumber、selenium 和 cucumber-spring 构建框架时遇到了设计问题.我的预期行为是为每个场景退出 WebdDriver 实例.但是

I have a design issue when I am trying to build a framework using cucumber, selenium and cucumber-spring. My expected behavior is to quit WebdDriver instance for every scenario. But

这是我在 srcmainjava

@Component
public class BasePage {
WebDriver driver;
 public BasePage(WebDriver driver) {
    this.driver = driver;
    PageFactory.initElements(driver, this);

 }
 public WebDriver getDriver() {
    return this.driver;
  }

}

这是另一个扩展 Base 类的页面对象类.

Here is another page object class which extends the Base class.

@Component
public class LoginPage extends BasePage
{
public LoginPage(WebDriver webDriver) {
    super(webDriver);
}

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[1]")
WebElement loginTextBox;

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[2]")
WebElement passwordTextBox;

@FindBy(xpath="/html/body/app-root/s-login-pg/div/form/button")
WebElement loginButton;

public void openApplication(String url){
    driver.get(url);
    waitForPageToLoad();
}

public void inputUsername(String username){
    loginTextBox.sendKeys(username);
}

public void inputPassword(String password){
    loginTextBox.sendKeys(password);
}

public void clickLoginButton(){
    loginButton.click();
 }
}

webdriver 是使用工厂设计模式创建的.根据属性文件中提到的浏览器,它将创建所需的 webdriver 实例.而且这些 Driver 类不是用 @Component

The webdriver is created with Factory Design pattern. Based on the browser mentioned in the properties file it will create the desired webdriver instance. And these Driver classes are not created with @Component

src/test/java下的spring配置类如下图.

And spring configuration class under src/test/java as shown below.

@Configuration
@ContextConfiguration(classes={PropertiesContext.class})
@ComponentScan(basePackages = "com.company.project")
public class CucumberContext {

@Autowired
private String browser;

  @Bean(name = "webdriver", destroyMethod = "quit")
  public WebDriver getWebDriver() {
    WebDriver webdriver = null;
    webdriver = DriverManagerFactory.getManager(browser).getDriver();
    return webdriver;
  }
}

这是srcestjava

public class StepDefinitions extends ParentSteps {

@Autowired
private LoginPage loginPage;

@Autowired
private HomePage homePage;

@Before
public void init() {
    if (System.getProperty("environment") == null) {
        System.setProperty("environment", "DEV");
    }
}

@After
public void tearDown(Scenario scenario) {
    if(loginPage.getDriver() != null) {
        loginPage.getDriver().quit;
    }
}

}

这是我在步骤定义中的实际问题.对于每个测试场景如果我调用 driver.quit() 其余测试场景将失败并出现以下异常,因为 bean WebDriver 在 @After

Here is my actual problem in the Step Definitions. For every Test Scenario If I call driver.quit() the remaining test scenarios will be failed with the below exception because the bean WebDriver killed in @After

org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?
Build info: version: '3.14.0', revision: 'aacccce0', time: '2018-08-02T20:19:58.91Z'
Driver info: driver.version: RemoteWebDriver

at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:125)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:548)

我收到此错误的原因是因为 webdriver 已关闭,它是一个 Injected bean.是否有任何解决方案可以在 @Before 中创建 wedriver 并在 @After 中为每个黄瓜场景杀死 webdriver?设计有什么缺陷吗?

The reason why I am getting this error is because the webdriver is closed which is an Injected bean. Is there any solution to create wedriver in @Before and kill webdriver in @After for each cucumber scenario? Is there any flaw in the design?

推荐答案

除了 OP 使用的@DirtiesContext 作为解决方案.尝试使用 @Scope(SCOPE_CUCUMBER_GLUE)/@Scope("cucumber-glue") .在每个场景中创建和销毁 Webdriver 的唯一实例.

Apart from the @DirtiesContext used by OP as solution . Tried using @Scope(SCOPE_CUCUMBER_GLUE)/@Scope("cucumber-glue") . Unique instance of Webdriver is created and destroyed in each scenario.

参考

将 Spring bean 的范围更改为 SCOPE_CUCUMBER_GLUE 会将其生命周期绑定到标准胶水生命周期.

Changing a Spring bean's scope to SCOPE_CUCUMBER_GLUE will bound its lifecycle to the standard glue lifecycle.

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;
import static io.cucumber.spring.CucumberTestContext.SCOPE_CUCUMBER_GLUE;

@Component
@Scope(SCOPE_CUCUMBER_GLUE)
public class MyComponent {
}

基本页面:

@Component
@Scope("cucumber-glue")
public class BasePage {
WebDriver driver;
 public BasePage(WebDriver driver) {
    this.driver = driver;
    PageFactory.initElements(driver, this);

 }
 public WebDriver getDriver() {
    return this.driver;
  }

}

基本页面:

@Component
@Scope("cucumber-glue")
public class LoginPage extends BasePage
{
public LoginPage(WebDriver webDriver) {
    super(webDriver);
}

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[1]")
WebElement loginTextBox;

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[2]")
WebElement passwordTextBox;

@FindBy(xpath="/html/body/app-root/s-login-pg/div/form/button")
WebElement loginButton;

public void openApplication(String url){
    driver.get(url);
   // waitForPageToLoad();
}

public void inputUsername(String username){
    loginTextBox.sendKeys(username);
}

public void inputPassword(String password){
    loginTextBox.sendKeys(password);
}

public void clickLoginButton(){
    loginButton.click();
 }
}

配置:

@Configuration
// Not define in example so commented @ContextConfiguration(classes=
//{PropertiesContext.class})
@ComponentScan(basePackages = "com.company.project")
public class CucumberContext {

@Autowired
private String browser;

  @Bean(name = "webdriver", destroyMethod = "quit")
  @Scope("cucumber-glue")
  public WebDriver getWebDriver() {
      WebDriver webdriver = null;
      // Removed the factory initialization code. Used simple ChromeDriver
      webdriver = new ChromeDriver();
      return webdriver;
  }
}

步骤:

public class StepDefinitions extends ParentSteps {

@Autowired
private LoginPage loginPage;

@Autowired
private HomePage homePage;

@Before
public void init() {
    if (System.getProperty("environment") == null) {
        System.setProperty("environment", "DEV");
    }
}

@After
public void tearDown(Scenario scenario) {
   // Removed quit
   // if(loginPage.getDriver() != null) {
   //     loginPage.getDriver().quit;
  //   }
}
}

注意:所有 chromeriver 后台进程都被杀死.

Note: All chromeriver background processes are killed.

这篇关于Cucumber spring WebDriver中的设计问题在@After方法中退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 20:28