Cucumber 中的设计问题 spring WebDriver 在 @After 方法中退出
Design issue in Cucumber spring WebDriver quit in @After method
我在尝试使用 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;
}
}
这是另一个页面对象 class,它扩展了基础 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 实例。这些驱动程序 classes 不是用 @Component
创建的
和spring配置class下src/test/java
如下图。
@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
下的步骤定义 class
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
中被杀死
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_CUCUMBER_GLUE)/@Scope("cucumber-glue") 。在每个场景中创建和销毁 Webdriver 的唯一实例。
将 Spring bean 的范围更改为 SCOPE_CUCUMBER_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、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;
}
}
这是另一个页面对象 class,它扩展了基础 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 实例。这些驱动程序 classes 不是用 @Component
和spring配置class下src/test/java
如下图。
@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
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
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_CUCUMBER_GLUE)/@Scope("cucumber-glue") 。在每个场景中创建和销毁 Webdriver 的唯一实例。
将 Spring bean 的范围更改为 SCOPE_CUCUMBER_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 后台进程都被杀死。