• Selenium+java


    前言

    上一小节我们已经学习了Page Object设计模式,优势很明显,能更好的体现java的面向对象思想和封装特性。但同时也存在一些不足之处,那就是随着这种模式使用,随着元素定位获取,元素定位与页面操作方法都在一个类里维护,会造成代码冗余度过高。

    相信使用过spring的同学肯定都知道,基于注解方式的开发,会大大提高开发效率,使代码块变得相对整洁,清晰。

    本小节要介绍的就是PageFactory 设计模式,同Page Object思想大体差不多,只是表现形式不太一样,只是通过注解方式来定位元素对象。

    一、@FindBy和@CacheLookup用法

    元素声明的写法:

        //定位 密码输入框
        @FindBy(name = "loginpassword")
        @CacheLookup
        private WebElement passWord;

    注解说明:

    @FindBy:这个注解的意思是说我们所查找的元素是以什么方式定位,

    @CacheLookup:这个注解的意思是说找到元素之后将缓存元素,重复的使用这些元素,将会大大加快测试的速度。

    WebElement passWord:就是变量名

    二、PageFactory类使用

    PageFactory提供的是静态方法,可以直接调用,一般在用完@FindBy后,需要进行元素初始化,则需要调用initElements(driver, this);方法。

    三、使用 PageFactory 模式来分离页面元素

    此处演示还沿用page object模式的风格,这里我又加了一层自己暂时定义叫基础层,现在就变成了四层:

    • 基础层:用来存放driver及初始化使用。
    • 对象层:用于存放页面元素定位和控件操作。
    • 操作层:则是一些封装好的功能用例模块。
    • 业务层:则是我们真正的测试用例的操作部分。

    下面将举例说明Page Object设计模式,我们还有360影视页面为例,来做进一步讲解。

    1、基础层

    先创建一个包,名为com.pagefactory.demo,接着在这个包下创建一个类名为HomePage,具体示例代码如下:

    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeDriver;
    import org.openqa.selenium.support.PageFactory;
    
    /**
     * @author rongrong
     * 基础页面
     */
    public class HomePage {
    
        private static WebDriver driver;
    
        /***
         * 用来传递WebDriver
         * @return
         */
        public static WebDriver driver() {
            return driver;
        }
    
        public HomePage() {
            //设置系统变量,并设置chromedriver的路径为系统属性值
            System.setProperty("webdriver.chrome.driver", "tool/chromedriver.exe");
            //实例ChromeDriver
            driver = new ChromeDriver();
            PageFactory.initElements(driver, this);
        }
    
        /**
         * 打开浏览器
         */
        public void open() {
            driver.get("https://i.360kan.com/login");
        }
    
        /**
         * 关闭浏览器
         */
        public void close() {
            driver.quit();
        }
    
        public LoginPage loginPage() {
            LoginPage loginPage = new LoginPage();
            return loginPage;
        }
    
    }

    这是我的基础页面,为了让driver抽离出去

    2、对象层

    接着我们再来创建一个类,名为LoginPage,具体示例代码如下:

    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.CacheLookup;
    import org.openqa.selenium.support.FindBy;
    import org.openqa.selenium.support.How;
    import org.openqa.selenium.support.PageFactory;
    
    /**
     * @author rongrong
     * 对象库层代码案例
     */
    public class LoginPage {
    
        public LoginPage(){
            PageFactory.initElements(HomePage.driver(),this);
        }
    
        //定位 用户名输入框
        @FindBy(how = How.NAME, using = "loginname")//第一种写法
        @CacheLookup
        private WebElement userName;
    
        //定位 密码输入框
        @FindBy(name = "loginpassword")//第二种写法
        @CacheLookup
        private WebElement passWord;
    
        //定位 登录按钮
        @FindBy(linkText = "立即登录")
        @CacheLookup
        private WebElement loginBtn;
    
        //定位 提示错误信息
        @FindBy(css = "[class='b-signin-error js-b-signin-error error-2']")
        @CacheLookup
        private WebElement errorMsg;
    
    
        public WebElement getUserName() {
            return userName;
        }
    
        public WebElement getPassWord() {
            return passWord;
        }
    
        public WebElement getLoginBtn() {
            return loginBtn;
        }
    
        public WebElement getErrorMsg() {
            return errorMsg;
        }
    
        /**
         * 用户名输入操作
         *
         * @param userName
         */
        public void sendKeysUserName(String userName) {
            getUserName().clear();
            getUserName().sendKeys(userName);
        }
    
        /**
         * 密码输入操作
         *
         * @param passWord
         */
        public void sendKeysPassWord(String passWord) {
            getPassWord().clear();
            getPassWord().sendKeys(passWord);
        }
    }

    3、操作层

    接着我们再来创建一个类,名为LoginMovies,用来记录登录的一系列操作,具体示例代码如下:

    package com.demo;
    
    import org.testng.Assert;
    
    /**
     * @author rongrong
     * 操作层代码案例
     */
    public class LoginMovies {
    
        /***
         * 登录过程
         * @param userName
         * @param pwd
         * @param expected
         */
        public void loginByPageFactory(String userName, String pwd, String expected) {
            HomePage homePage = new HomePage();
            //打开登录页
            homePage.open();
            //输入用户名
            homePage.loginPage().sendKeysUserName(userName);
            //输入密码
            homePage.loginPage().sendKeysPassWord(pwd);
            //点击登录
            homePage.loginPage().getLoginBtn().click();
            //获取提示语操作
            String msg = homePage.loginPage().getErrorMsg().getText();
            //验证输入手机号错误是否提示
            Assert.assertEquals(msg, expected);
            //关闭浏览器
            homePage.close();
        }
    }

    4、业务层

    最后我们再来创建一个类,名为TestPageFactory,用来验证登录功能,具体示例代码如下:

    import org.testng.annotations.Test;
    
    /**
     * @author rongrong
     * 业务层代码案例
     */
    public class TestPageFactory {
    
    
        /**
         * 测试登录
         */
        @Test
        public void textLogin() {
            //实例化操作对象
            LoginMovies loginMovies = new LoginMovies();
            //登录操作
            loginMovies.loginByPageFactory("your userName", "your passWord", "输入手机号不合法");
        }
    
    
    }

    从以上代码看,如果页面元素发生变化,我们在对应类里修改对应元素即可,而操作和业务层流程类及用例都不用改,如果仅是业务流程更改,只需要维护业务层流程类业务脚本,其他几个类都不用改,从而做到了很好的将页面、元素、脚本进行了分离。

    关于PageObject & PageFactory的使用,这里仅为读者提供了思路,有兴趣的同学可以继续拓展,笔者能力有限,如果觉得文章好,还请添加关注我哦

  • 相关阅读:
    5.JavaSE之数据类型详解
    4.JavaSE之标识符
    2.Java程序运行机制
    1.HelloWorld 仪式感
    10.安装开发环境
    【模板】后缀数组
    Luogu P3808 【模板】AC自动机(简单版)
    Luogu P3375 【模板】KMP字符串匹配
    LNSY集训
    Luogu P2580 于是他错误的点名开始了 (Trie树模板)
  • 原文地址:https://www.cnblogs.com/longronglang/p/11386471.html
Copyright © 2020-2023  润新知