Java Cucumber spring WebDriver中的设计问题在@After方法中退出

Java Cucumber spring WebDriver中的设计问题在@After方法中退出,java,spring,selenium,selenium-webdriver,cucumber,Java,Spring,Selenium,Selenium Webdriver,Cucumber,当我试图使用cucumber、selenium和cucumber spring构建一个框架时,我遇到了一个设计问题。我的预期行为是针对每个场景退出WebdDriver实例。但是 这是我在src\main\java @Component public class BasePage { WebDriver driver; public BasePage(WebDriver driver) { this.driver = driver; PageFactory.initElement

当我试图使用cucumber、selenium和cucumber spring构建一个框架时,我遇到了一个设计问题。我的预期行为是针对每个场景退出WebdDriver实例。但是

这是我在
src\main\java

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

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

}
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;
    }
}
下面是另一个扩展基类的页面对象类

@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是使用Factory设计模式创建的。基于属性文件中提到的浏览器,它将创建所需的webdriver实例。并且这些驱动程序类不是使用
@组件创建的

src/test/java
下的spring配置类,如下所示

@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;
  }
}
这是
src\test\java

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

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

}
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在
@之后被杀死

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是关闭的,它是一个注入的bean。对于每个场景,是否有任何解决方案可以在@Before中创建wedriver并在@After中杀死webdriver?设计中是否存在任何缺陷?

除了OP用作解决方案的@DirtiesContext之外。尝试使用@Scope(Scope\u cumber\u GLUE)/@Scope(“cumber GLUE”)。在每个场景中创建并销毁Webdriver的唯一实例

将Springbean的scope更改为scope\u cumber\u GLUE会将其生命周期绑定到标准的GLUE生命周期

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;
  //   }
}
}

注意:除OP用作解决方案的@DirtiesContext外,所有chromeriver后台进程都将被终止。

。尝试使用@Scope(Scope\u cumber\u GLUE)/@Scope(“cumber GLUE”)。在每个场景中创建并销毁Webdriver的唯一实例

将Springbean的scope更改为scope\u cumber\u GLUE会将其生命周期绑定到标准的GLUE生命周期

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后台进程都将被终止。

您是按顺序还是并行运行场景?cucumber的版本是什么?我正在按顺序运行场景。我也尝试过并行,但没有成功。我使用的是最新版本
1.2.5
是否有任何特定原因要在@After中退出驱动程序?在黄瓜的春天,你必须找到等效的解决方案。cucumber guice
@DirtiesContext
中类似于“@ScenarioScoped”的东西可以工作,但是测试速度非常慢,因为每次加载上下文都要花费很多时间test@vkrams通过在所有组件(页面)+@Bean(name=“webdriver”)上使用@Scope(“cucumber glue”)尝试上述示例。正常工作,没有观察到慢度。您是按顺序还是并行运行您的场景?cucumber的版本是什么?我正在按顺序运行场景。我也尝试过并行,但没有成功。我使用的是最新版本
1.2.5
是否有任何特定原因要在@After中退出驱动程序?在黄瓜的春天,你必须找到等效的解决方案。cucumber guice
@DirtiesContext
中类似于“@ScenarioScoped”的东西可以工作,但是测试速度非常慢,因为每次加载上下文都要花费很多时间test@vkrams通过在所有组件(页面)+@Bean(name=“webdriver”)上使用@Scope(“cucumber glue”)尝试上述示例。正常工作,没有观察到缓慢。事实上,我不需要调用
driver.quit()
spring上下文本身来分解驱动程序实例。是的,我观察到了这一点。因此,我在@After方法中为quit callInfact注释了代码,我不需要调用
driver.quit()
spring上下文本身来分解驱动程序实例。是的,我观察到了这一点。所以我在@After方法中为quit调用注释了代码