Java页面对象模型最佳实践-新对象

Java页面对象模型最佳实践-新对象,java,automation,cucumber,pageobjects,Java,Automation,Cucumber,Pageobjects,在Java页面对象模型中创建步骤时实例化对象的最佳方法是什么 有人知道Cucumber脚本是如何编译的吗 我想,如果一切都建成并符合要求,下面的第二个或第三个选项可能是最好的方法 如果只编译与正在执行的测试相关的步骤,那么我认为这将是第一步 我举了以下例子: private LoginPage loginPage = new LoginPage(driver); @Given("^I have logged in as customer with two stored cards$") pub

在Java页面对象模型中创建步骤时实例化对象的最佳方法是什么

有人知道Cucumber脚本是如何编译的吗

我想,如果一切都建成并符合要求,下面的第二个或第三个选项可能是最好的方法

如果只编译与正在执行的测试相关的步骤,那么我认为这将是第一步

我举了以下例子:

private LoginPage loginPage = new LoginPage(driver);

@Given("^I have logged in as customer with two stored cards$")
public void iHaveLoggedInAsCustomerWithTwoStoredCards() throws Throwable {
    new HomePage(driver).clickLoginButton();
    loginPage.enterEmail("test@test.com");
    loginPage.enterPassword("Password1");
    loginPage.clickLogin();        
}

@Given("^I have logged in as customer with expired card$")
public void iHaveLoggedInAsCustomerWithExpiredCard() throws Throwable {
    new HomePage(driver).clickLoginButton();
    loginPage.enterEmail("test02@test.com");
    loginPage.enterPassword("Password1");
    loginPage.clickLogin();        
}

@Given("^the user logged in as customer with three stored cards$")
public void theUserLoggedInAsCustomerWithThreeStoredCards() throws Throwable {
    new HomePage(driver).clickLoginButton();
    loginPage.enterEmail("test03@test.com");
    loginPage.enterPassword("Password1");
    loginPage.clickLogin();        
}
以上所有步骤(以及同一LoginSteps.java类中的更多步骤)都从

new HomePage(driver).clickLoginButton();
这是最好的方法,还是创建一个实例更好

private LoginPage loginPage = new LoginPage(driver);
private HomePage homePage = new HomePage(driver);

@Given("^I have logged in as customer with two stored cards$")
public void iHaveLoggedInAsCustomerWithTwoStoredCards() throws Throwable {
    homePage.clickLoginButton();
    loginPage.enterEmail("test@test.com");
    loginPage.enterPassword("Password1");
    loginPage.clickLogin();        
}

@Given("^I have logged in as customer with expired card$")
public void iHaveLoggedInAsCustomerWithExpiredCard() throws Throwable {
    homePage.clickLoginButton();
    loginPage.enterEmail("test02@test.com");
    loginPage.enterPassword("Password1");
    loginPage.clickLogin();        
}

@Given("^the user logged in as customer with three stored cards$")
public void theUserLoggedInAsCustomerWithThreeStoredCards() throws Throwable {
    homePage.clickLoginButton();
    loginPage.enterEmail("test03@test.com");
    loginPage.enterPassword("Password1");
    loginPage.clickLogin();        
}
或者在LoginSteps扩展的“baseSteps”类中实例化所有页面是否更有效

public class LoginSteps extends BaseSteps {
    @Given("^I have logged in as customer with two stored cards$")
    public void iHaveLoggedInAsCustomerWithTwoStoredCards() throws Throwable {
        homePage.clickLoginButton();
        loginPage.enterEmail("test@test.com");
        loginPage.enterPassword("Password1");
        loginPage.clickLogin();        
    }

    @Given("^I have logged in as customer with expired card$")
    public void iHaveLoggedInAsCustomerWithExpiredCard() throws Throwable {
        homePage.clickLoginButton();
        loginPage.enterEmail("test02@test.com");
        loginPage.enterPassword("Password1");
        loginPage.clickLogin();        
    }

    @Given("^the user logged in as customer with three stored cards$")
    public void theUserLoggedInAsCustomerWithThreeStoredCards() throws Throwable {
        homePage.clickLoginButton();
        loginPage.enterEmail("test03@test.com");
        loginPage.enterPassword("Password1");
        loginPage.clickLogin();        
    }
}

public baseSteps {

    protected LoginPage loginPage = new LoginPage(driver);
    protected HomePage homePage = new HomePage(driver);
}

我会进行基准测试,看看哪个版本最有效

Cucumber代码的编译方式取决于构建工具。我假设所有的东西都是在使用之前编译好的。但是一个JVM在执行一段时间后会自我优化,一段时间后可能会表现出不同的行为


我真的很想听听你为什么要考虑这个级别的性能tho?您是否希望一次执行此代码数小时?我的大多数场景都很短,在第二个规模上执行,然后被丢弃。

您的Cucumber测试是否针对GUI运行?如果是这样,那么创建给定页面对象的单个实例还是多个实例都不会有什么区别。这种测试本质上是缓慢的,这样的调整是难以察觉的

不管是什么情况,优先考虑的总是一个好的设计。一个好的设计不仅可以简化代码的未来维护,还可以让您改进系统性能。然而,事实并非如此

cumber页面对象模型非常适合。但它们应该被安排在单独的层中,Cucumber位于页面对象模型的顶部,充当后者的客户机。看着你的代码示例,我不明白为什么页面对象是作为步骤定义代码的一部分创建的。为什么clickLoginButton方法本身不返回LoginPage的实例

在我看来,页面对象模型应该由两个基本原则支持:
1. API。每个页面对象都应该定义一个API,其方法与用户可以在该页面上执行的操作相对应。
2. 导航。每个操作都应该将用户带到相同的页面或不同的页面。因此,每个方法都应该返回页面对象本身或不同的页面对象

第一个是由您的代码实现的,但第二个不是,或者至少不够清楚

我认为HomePage和LoginPage类是这样的(不需要太多细节):

至于黄瓜层,我认为它如下(同样,不太详细):

请参阅最后一个方法中的(可选)方法链接,这是页面对象模型的方法返回的页面对象的结果

@Before
public void setUp() {
    homePage = new HomePage(driver);
}
我故意省略了变量主页、loginPage和nextPage的声明。LoginSteps不会与其他步骤类共享变量,即使您使它们从公共BaseSteps类扩展,除非您将它们声明为静态:

public BaseSteps {
    protected static HomePage homePage;
    protected static LoginPage loginPage;
    protected static NextPage nextPage;
    ...
}

您可以考虑集成依赖注入框架,但我没有尝试过。

将变量保留为私有实例属性将不起作用(即使它们没有与其他步骤类共享),因为Cucumber使用类中包含的步骤定义为每个测试场景实例化步骤类

最后,Cucumber层中应该有一个钩子来初始化页面对象模型的入口点

@Before
public void setUp() {
    homePage = new HomePage(driver);
}

这应该是唯一一个从Cucumber层显式创建的页面对象。

我将试一试,看看是否有任何不同。这样做的理由是因为我将持续运行这些程序,我需要它们尽可能高效。谢谢你的帮助。
@Before
public void setUp() {
    homePage = new HomePage(driver);
}