Java Cucumber spring WebDriver中的设计问题在@After方法中退出
当我试图使用cucumber、selenium和cucumber spring构建一个框架时,我遇到了一个设计问题。我的预期行为是针对每个场景退出WebdDriver实例。但是 这是我在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
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调用注释了代码