Selenium+java - Page Object設計模式


前言

Page Object(頁面對象)模式,是Selenium實戰中最為流行,並且被自動化測試同學所熟悉和推崇的一種設計模式之一。在設計測試時,把頁面元素定位和元素操作方法按照頁面抽象出來,分離成一定的對象,然后再進行組織。

相信每個做自動化測試的同學,一定會遇到這樣一個非常頭疼的問題,那就是頁面變化,如果沒有使用Page Object設計模式,這就意味着以前的定位元素方法不能用了,需要重新修改元素定位方式。你需要一個一個從測試腳本中把需要修改的元素定位方式找出來,然后再進行修改。這勢必會使腳本維護的成本變高,顯然這樣的自動化腳本就不會有人願意使用。

那這時我們使用page object模式就可以解決這個問題了。

PageObject 的優點

  • 減少代碼冗余
  • 業務和實現分離
  • 降低代碼維護成本

Page Object模式

Page Object 見名知意,就是頁面對象,並將頁面元素定位方法和元素操作進行分離。

在實際自動化測試實戰過程中,我們一般對腳本的實現分為三層:

  • 對象層:用於存放頁面元素定位和控件操作。
  • 邏輯層:則是一些封裝好的功能用例模塊。
  • 業務層:則是我們真正的測試用例的操作部分。

使用 Page Object 類來分離頁面元素

我們以360影視登錄頁為測試對象,先創建一個包com.pageobject.demo

對象層

首先我們新建一個類LoginPage,登錄頁面內編寫需要操作的元素定位方式和控件操作,具體代碼示例如下:

package com.pageobject.demo;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Assert;

/**
 * @author rongrong
 * 對象庫層代碼案例
 */
public class LoginPage {

    WebDriver driver;

    //定位 用戶名輸入框
    public static By userNameInput = By.name("loginname");
    //定位 密碼輸入框
    public static By passWordInput = By.name("loginpassword");
    //定位 登錄按鈕
    public static By loginBtn = By.linkText("立即登錄");
    //定位 提示錯誤信息
    public static By errorMsg = By.cssSelector("[class='b-signin-error js-b-signin-error error-2']");

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


    /**
     * 用戶名輸入操作
     *
     * @param userName
     */
    public void sendKeysUserName(String userName) {
        driver.findElement(userNameInput).clear();
        driver.findElement(userNameInput).sendKeys(userName);
    }

    /**
     * 密碼輸入操作
     *
     * @param passWord
     */
    public void sendKeysPassWord(String passWord) {
        driver.findElement(passWordInput).clear();
        driver.findElement(passWordInput).sendKeys(passWord);
    }
}

這里我只對用戶名和密碼輸入框進行了封裝,有興趣的同學也可以接着進行全部元素操作封裝

操作層

我們再新建一個類LoginMovies,用於登錄邏輯的封裝,供業務層調用,具體代碼示例如下:

package com.pageobject.demo;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.testng.Assert;

/**
 * @author rongrong
 * 操作層代碼案例
 */
public class LoginMovies {
    WebDriver driver;

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

    /**
     * 登錄操作
     *
     * @param userName
     * @param pwd
     * @param expected
     */
    public void login(String userName, String pwd, String expected) {
        LoginPage loginPage = new LoginPage(driver);
        //輸入用戶名
        loginPage.sendKeysUserName(userName);
        //輸入密碼
        loginPage.sendKeysPassWord(pwd);
        //點擊登錄
        driver.findElement(LoginPage.loginBtn).click();
        //獲取提示語操作
        String msg = driver.findElement(LoginPage.errorMsg).getText();
        Assert.assertEquals(msg, expected);
    }
}

業務層

最后我們新建一個類TestPageObject,用於業務層的封裝,具體代碼示例如下:

package com.pageobject.demo;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import java.util.concurrent.TimeUnit;

/**
 * @author rongrong
 * 業務層代碼案例
 */
public class TestPageObject {

    /**
     * 360影視登錄頁
     */
    public static final String URL = "https://i.360kan.com/login";
    WebDriver driver;

    @BeforeClass
    public void BeforeClass() {
        //設置系統變量,並設置chromedriver的路徑為系統屬性值
        System.setProperty("webdriver.chrome.driver", "tool/chromedriver.exe");
        //實例ChromeDriver
        driver = new ChromeDriver();
        driver.get(URL);
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.manage().window().maximize();
    }

    /**
     * 測試登錄
     */
    @Test
    public void testLogin() {
        //實例化操作對象
        LoginMovies loginMovies = new LoginMovies(driver);
        loginMovies.login("your userName", "your passWord", "輸入手機號不合法");
    }

    @AfterClass
    public void closedChrome() {
        driver.quit();
    }

}

小結

雖然該實現方法看上去復雜多了,但其中的設計好處是不同層關心不同的問題。頁面對象只關心元素的定位,測試用例只關心測試數據。

LoginPage類中主要對登錄頁面上元素進行封裝,使其成為具體的操作方法。如對用戶名、密碼框都封裝成方法,然后定義login(String userName, String pwd, String expected)方法將單個元素操作組成一個完整的動作,包含輸入用戶名、密碼並點擊登錄按鈕等。

使用時將driver、username、pwd、expected作為函數的入參,這樣的方法具有很強的可重用性。

最后使用testLogin()方法進行用戶操作行為,現在只關心用哪個瀏覽器、登錄的用戶名和密碼是什么,至少輸入框、按鈕是如何定位的,則不關心。即實現了不同層關心不同問題。如果再有定位元素變化,只需LoginPage這個類維護即可,顯然方便了很多。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM