2016-11-04 66 views
3

我有理解這種模式的問題。 首先,我想測試我的頁面中的登錄,我有一個LoginPage,它在成功驗證後擴展了我的PageObject,它返回LoginPageReceipt。現在,我已經loginPageReceipt我想保留這爲我的第二頁。我想的第二個問題是,如果首先我測試登錄然後我想測試下一個模塊,但我必須登錄。我應該怎麼做?我的第二個測試不應該使用第一次測試的結果,我不應該複製我的代碼。這是我的課程。我是如何做到的。頁面對象模式理解

package Init; 

import org.junit.After; 
import org.junit.AfterClass; 
import org.junit.BeforeClass; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.chrome.ChromeDriver; 
import org.openqa.selenium.chrome.ChromeOptions; 

import java.util.concurrent.TimeUnit; 

public class FunctionalTest { 
    protected static WebDriver driver; 
// private static WebDriverWait driverWait; 

    @BeforeClass 
    public static void setUp() { 
     ChromeOptions options = new ChromeOptions(); 
     options.addArguments("--start-maximized"); 
     System.setProperty("webdriver.chrome.driver", "src\\main\\resources\\chromedriver.exe"); 
     driver = new ChromeDriver(options); 
     driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); 
//  driverWait = new WebDriverWait(driver, 10); 
    } 

    @After 
    public void cleanUp() { 
     driver.manage().deleteAllCookies(); 
    } 

    @AfterClass 
    public static void tearDown() { 
     driver.close(); 
    } 
} 

package Init; 

import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.support.PageFactory; 

public class PageObject { 

    protected WebDriver driver; 

    public PageObject(WebDriver driver) { 
     this.driver = driver; 
     PageFactory.initElements(driver, this); 
    } 

} 
package Login; 

import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.FindBy; 
import Init.PageObject; 

import static org.junit.Assert.assertTrue; 

public class LoginPage extends PageObject { 

    @FindBy(id = "UserName") 
    private WebElement userName; 

    @FindBy(id = "Password") 
    private WebElement password; 

    @FindBy(id = "loginButton") 
    private WebElement loginButton; 

    public LoginPage(WebDriver driver) { 
     super(driver); 
     assertTrue(userName.isDisplayed()); 
     assertTrue(password.isDisplayed()); 
     assertTrue(loginButton.isDisplayed()); 
    } 

    public void enterUserName(String userName) { 
     this.userName.clear(); 
     this.userName.sendKeys(userName); 
    } 

    public void enterUserPassword(String password) { 
     this.password.clear(); 
     this.password.sendKeys(password); 
    } 

    public LoginPageReceipt login() { 
     loginButton.click(); 
     return new LoginPageReceipt(driver); 
    } 
} 

package Contractor; 

import Init.PageObject; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.FindBy; 

import static org.junit.Assert.assertTrue; 

public class ContractorPage extends PageObject { 

    @FindBy(id = "moduleContent") 
    private WebElement moduleContent; 

    public ContractorPage(WebDriver driver) { 
     super(driver); 
     assertTrue(moduleContent.isDisplayed()); 
    } 
} 

package Login; 

import Contractor.ContractorPage; 
import org.openqa.selenium.WebDriver; 
import org.openqa.selenium.WebElement; 
import org.openqa.selenium.support.FindBy; 
import Init.PageObject; 

public class LoginPageReceipt extends PageObject { 

    @FindBy(xpath = "//*[@id=\"loginPartial\"]/span[5]") 
    private WebElement userNamePanel; 

    @FindBy(id = "contractors-menuitem") 
    private WebElement goToContractorPage; 

    public LoginPageReceipt(WebDriver driver) { 
     super(driver); 
    } 

    public String loginConfirmation() { 
     return userNamePanel.getText(); 
    } 

    public ContractorPage contractorPage() { 
     goToContractorPage.click(); 
     return new ContractorPage(driver); 
    } 
} 

package Tests; 

import Login.LoginPage; 
import Login.LoginPageReceipt; 
import org.junit.Test; 
import Init.FunctionalTest; 

import static org.junit.Assert.assertEquals; 

public class LoginTest extends FunctionalTest { 

    private static final String USER_NAME = "xxx"; 
    private static final String PASSWORD = "xxx"; 

    @Test 
    public void login() { 
     FunctionalTest.driver.get("xxx"); 

     LoginPage loginPage = new LoginPage(FunctionalTest.driver); 
     loginPage.enterUserName(USER_NAME); 
     loginPage.enterUserPassword(PASSWORD); 
     LoginPageReceipt loginPageReceipt = loginPage.login(); 

     assertEquals("Użytkownik: " + USER_NAME + " | Wyloguj", loginPageReceipt.loginConfirmation()); 
    } 

} 

package Tests; 

import Contractor.ContractorPage; 
import Init.FunctionalTest; 
import Login.LoginPage; 
import Login.LoginPageReceipt; 
import org.junit.Test; 

import static org.junit.Assert.assertEquals; 

public class ContractorTest extends FunctionalTest { 

    private static final String USER_NAME = "xxx"; 
    private static final String PASSWORD = "xxx"; 

    @Test 
    public void contractorPageTest() { 
     FunctionalTest.driver.get("xxx"); 

     LoginPage loginPage = new LoginPage(FunctionalTest.driver); 
     loginPage.enterUserName(USER_NAME); 
     loginPage.enterUserPassword(PASSWORD); 
     LoginPageReceipt loginPageReceipt = loginPage.login(); 

     assertEquals("Użytkownik: " + USER_NAME + " | Wyloguj", loginPageReceipt.loginConfirmation()); 

     ContractorPage contractorPage = loginPageReceipt.contractorPage(); 
    } 
} 

回答

1

關於頁面對象模型的一個優點是它是一個通用指南,而不是一個嚴格的系統。每個人都喜歡他們如何模擬他們的硒項目。

要回答你的直接問題,有一個頁面對象的方法觸發一個新的頁面加載到瀏覽器中,返回一個表示該頁面的新頁面對象是完全有效的。

就每個單獨的測試而言,除非您試圖在一個測試間保存Web應用程序中的有狀態信息(對於我來說這通常是一個壞主意),那麼是的,您需要每次測試來重複此操作登錄程序。但它不一定是重複的代碼,將這個例程封裝在一個方法中,每個測試都可以稱爲第一階段的業務。此外,執行過程與測試過程不一樣,您對登錄頁面的測試應該斷言事情正確,需要以中間步驟登錄的其他測試應該跳過這些斷言。

另外,頁面對象不需要封裝整個頁面。你想要考慮你正在測試的應用程序的設計。並非所有的應用程序都自動實現自動化,因此硒項目不應該具有普遍性。

如果您的應用程序是靜態頁面的集合,並沒有發生狀態變化,那麼您可能希望每個網頁都有一個頁面對象。但是如果你有一個單獨的頁面應用程序,它只是讓頁面的大部分區域頻繁出現和消失......也許你的頁面對象可以更好地封裝單個頁面的區域,代表來去的組件或框架,但是在自己內部是一致的。

從概念的角度來看,您希望您的頁面對象隱藏所有原始硒,以便您的測試不需要知道或關心,並提供一個簡潔的公共API,您的測試可以在該頁面上執行操作。

無論您的頁面對象的方法是封裝頁面上的小型小型操作(例如表單中每個字段的單獨方法),還是更大型的工作流程(例如填充整個表單並提交它的方法)都取決於您。這個決定應該考慮應用程序的設計,你的目標是做一些不僅可靠,而且易於創建新內容並易於維護現有內容的東西。

編輯:

這裏有一個理論上的登錄頁面對象的示例:

public class LoginPage { 
    private final WebDriver driver; 

    private final String emailField = "#email"; 
    private final String passwordField = "#password"; 
    private final String submitButton = "#submit"; 

    public LoginPage(WebDriver driver) { 
     this.driver = driver; 
    } 

    // These are our bite sized methods right here 
    public LoginPage enterEmail(String email) { 
     driver.findElement(By.cssSelector(emailField)).sendKeys(email); 
     return this; 
    } 

    public LoginPage enterPassword(String password) { 
     driver.findElement(By.cssSelector(passwordField)).sendKeys(password); 
     return this; 
    } 

    public void submit() { 
     driver.findElement(By.cssSelector(submitButton)).click(); 
    } 

    // This method represents an entire workflow, 
    // containing multiple bite-sized chunks. 
    public void performLogin(String email, String password) { 
     enterEmail(email); 
     enterPassword(password); 
     submit(); 
    } 
} 

要使用,您的測試可以這樣做:

WebDriver driver = new ChromeDriver(options); 
LoginPage loginPage = new LoginPage(driver); 

//One way: 
loginPage.enterEmail("[email protected]").enterPassword("12345").submit(); 

// Another way: 
loginPage.performLogin("[email protected]", "12345"); 

如果你知道確切位置您將被重定向到,您的submitperformLogin方法可以返回您的下一個頁面對象的實例。

0

其他答案很好,並澄清您的問題。我想在這個答案中提出一個框架。

enter image description here

你的測試類不應該知道什麼硒。它應該只與Page對象交互。頁面對象通過頁面片段與瀏覽器交互。頁面片段處理webdriver。

正如您使用硒+ java,看看Arquillian - Graphene。它是一組庫,可以幫助您在Java + Selenium中創建更好的框架。您可以添加庫&只需選擇不使用。基本上它不會搞亂你現有的腳本。

優點:

  • 你不需要頁面工廠。一切都在運行時爲你注入。包括司機。
  • AJAX處理
  • jQuery選擇
  • AngularJS選擇

還有更多。

對於例如:在你的情況,

public class LoginPage { 
... 
... 
... 
} 


public class LoginPageReceipt { 
... 
... 
... 
} 



public class ContractorPage { 
... 
... 
... 
} 

測試類

public class LoginTest{ 

    @Page 
    LoginPage loginPage; 

    @Page 
    LoginPageReceipt loginPageReceipt; 

    @Test 
    public void login() { 
     loginPage.enterUserName(USER_NAME); 
     loginPage.enterUserPassword(PASSWORD); 
     loginPage.login(); 
     assertEquals("Użytkownik: " + USER_NAME + " | Wyloguj", loginPageReceipt.loginConfirmation()); 
    } 

} 

檢查here例如。