Java自动化测试(web自动化测试框架 )

news2024/11/16 6:55:49

 

测试数据

测试地址

http://120.78.128.25:8765/

投资人

13323234545

lemon123456

借款人

13323234444

lemonbest

后台地址

http://120.78.128.25:8765/Admin/Index/login.html

lemon7

lemonbest

Page Object

PO简介

https://www.selenium.dev/documentation/en/guidelines_and_recommendations/page_object_models/

Page Object 是 Selenium 自动化测试项目开发实践的最佳设计模式之一,Page Object 的主要体现于对界面交互细节的封装,这样可以使测试案例更关注与业务而非界面细节,提高测试案例的可读性。

Page Object 设计模式的优点如下:

  • 减少代码的重复;
  • 提高测试用例的可读性;
  • 提高测试用例的可维护性,特别是针对 UI 频繁变化的项目;

Paget Object 使用注意:

  • public方法代表Page提供的功能
  • 尽量不要暴露Page的内部细节
  • 不要assertion
  • 方法可以返回其他Page Objects
  • Page Objects不用代表整个页面,可以是任意一个部分
  • 一样的操作,不同的结果应该分开(正确登录,错误登录)

使用po是对页面进行抽象或者说建模的过程,需要把页面当作一个对象。

面向对象编程语言中,进行面向对象编程需要考虑以下两点:

  1. 对象的属性「全局变量」 == web页面的元素「定位方法,定位值」
  2. 对象的行为「方法」 == web页面的元素的操作

编写页面操作基类

package com.zhongxin.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class BasePage {
    private WebDriver driver;

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

    /**
     * 封装显式等待
     *
     * @param by 元素定位信息
     * @return 元素对象
     */
    public WebElement waitElementBisibility(By by) {
        WebElement element = null;
        try {
            //5秒元素可见显式等待
            WebDriverWait wait = new WebDriverWait(driver, 5);
            element = wait.until(ExpectedConditions.visibilityOfElementLocated(by));
            return element;
        } catch (Exception e) {
            System.out.println("元素定位异常" + e.getMessage());
        }
        return null;
    }
}

登陆页面封装

package com.zhongxin.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public class LoginPage extends BasePage {

    private WebDriver driver;

    // phone元素定位信息
    private By phoneBy = By.name("phone");
    //password元素定位信息
    private By passwordBy = By.name("password");
    //登陆按钮元素定位信息
    private By loginBtnBy = By.xpath("//button[@class='btn btn-special']");
    //页面中央错误提示
    private By centerErrorBy = By.className("layui-layer-content");
    //页面手机红色错误提示
    private By phoneformErrorBy = By.xpath("//input[@name='phone']//following-sibling::div");
    //页面密码红色错误提示
    private By passwordformErrorBy = By.xpath("//input[@name='password']//following-sibling::div");

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


    //对手机框进行输入
    public void inputPhone(String phone) {
        WebElement element = waitElementBisibility(phoneBy);
        if (element != null) {
            element.clear();
            element.sendKeys(phone);
        }
    }

    //对密码框进行输入
    public void inputPassword(String password) {
        WebElement element = waitElementBisibility(passwordBy);
        if (element != null) {
            element.clear();
            element.sendKeys(password);
        }
    }

    //点击登陆按钮
    public void clickLoginBtn() {
        WebElement element = waitElementBisibility(loginBtnBy);
        if (element != null) {
            element.click();
        }

    }

    //获取页面中央错误提示文本
    public String getCenterErrorText() {
        WebElement element = waitElementBisibility(centerErrorBy);
        if (element != null) {
            return element.getText();
        }
        return "";
    }

    //获取页面手机红色错误提示
    public String getPhoneFormErrorText() {
        WebElement element = waitElementBisibility(phoneformErrorBy);
        if (element != null) {
            return element.getText();
        }
        return "";
    }

    //获取页面手机红色错误提示
    public String getPasswordFormErrorText() {
        WebElement element = waitElementBisibility(passwordformErrorBy);
        if (element != null) {
            return element.getText();
        }
        return "";
    }


}

首页封装

package com.zhongxin.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.WebDriverWait;

public class IndexPage extends BasePage {
    private WebDriver driver;

    //昵称
    private By nicknameBy = By.xpath("//a[contains(text(),'我的帐户[自动化测试帐号1]')]");

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


    // 昵称是否可见
    public boolean nicknameIsVisibility() {
        WebElement element = waitElementBisibility(nicknameBy);
        if (element != null) {
            return element.isDisplayed();
        }
        return false;
    }

}

测试代码

package com.zhongxin.cases;

import com.zhongxin.pages.IndexPage;
import com.zhongxin.pages.LoginPage;
import okio.Timeout;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;


public class LoginCase {
    public WebDriver driver;

    @BeforeClass
    public void setUp() {
        //打开浏览器
        driver = open("chrome");
        //访问登陆页面
        driver.get("http://120.78.128.25:8765/Index/login.html");
    }

    @Test
    public void testFailed01() throws InterruptedException {
        LoginPage loginpage = new LoginPage(driver);
        loginpage.inputPhone("13212312312");
        loginpage.inputPassword("123123123");
        loginpage.clickLoginBtn();
        String actual = loginpage.getCenterErrorText();
        String expected = "此账号没有经过授权,请联系管理员!";
        Assert.assertEquals(actual, expected);
    }

    @Test
    public void testFailed02() throws InterruptedException {
        LoginPage loginpage = new LoginPage(driver);
        loginpage.inputPhone("");
        loginpage.inputPassword("123123123");
        loginpage.clickLoginBtn();
        String actual = loginpage.getPhoneFormErrorText();
        String expected = "请输入手机号";
        Assert.assertEquals(actual, expected);
    }

    @Test(dataProvider = "datas")
    public void testFailed03(String phone, String password, String expected) throws InterruptedException {
        LoginPage loginpage = new LoginPage(driver);
        loginpage.inputPhone(phone);
        loginpage.inputPassword(password);
        loginpage.clickLoginBtn();
        String actual = loginpage.getPhoneFormErrorText();
        Assert.assertEquals(actual, expected);
    }

    @Test
    public void testFailed04() throws InterruptedException {
        LoginPage loginpage = new LoginPage(driver);
        loginpage.inputPhone("15859019251");
        loginpage.inputPassword("");
        loginpage.clickLoginBtn();
        String actual = loginpage.getPasswordFormErrorText();
        Assert.assertEquals(actual, "请输入密码");
    }

    @Test
    public void testFailed05() throws InterruptedException {
        LoginPage loginpage = new LoginPage(driver);
        loginpage.inputPhone("13323234545");
        loginpage.inputPassword("123123123");
        loginpage.clickLoginBtn();
        String actual = loginpage.getCenterErrorText();
        Assert.assertEquals(actual, "帐号或密码错误!");
    }

    @Test
    public void testSuccess() throws InterruptedException {
        LoginPage loginpage = new LoginPage(driver);
        loginpage.inputPhone("13323234545");
        loginpage.inputPassword("lemon123456");
        loginpage.clickLoginBtn();
        Thread.sleep(2000);
        IndexPage indexPage = new IndexPage(driver);
        boolean flag = indexPage.nicknameIsVisibility();
        Assert.assertTrue(flag);

    }

    @DataProvider
    public Object[][] datas() {
        Object[][] datas = {
                {"", "123123123", "请输入手机号"},
                {"1585901925", "123123123", "请输入正确的手机号"},
                {"158590192534", "123123123", "请输入正确的手机号"},
                {"1585901925%", "123123123", "请输入正确的手机号"},
        };
        return datas;
    }

    @AfterClass
    public void tearDown() throws InterruptedException {
        Thread.sleep(2000);
        //关闭浏览器
        close(driver);
    }


    public static void close(WebDriver driver) throws InterruptedException {
        Thread.sleep(3000);
        driver.quit();
    }

    public static WebDriver open(String type) {
        WebDriver driver = null;
        if ("chrome".equalsIgnoreCase(type)) {
            System.setProperty("webdriver.chrome.driver", "src/test/resources/chromedriver");
            driver = new ChromeDriver();
        } else if ("ie".equalsIgnoreCase(type)) {
            // 设置ie启动项
            DesiredCapabilities capabilities = new DesiredCapabilities();
            // 忽略缩放
            capabilities.setCapability(InternetExplorerDriver.IGNORE_ZOOM_SETTING, true);
            // 忽略保护模式
            capabilities.setCapability(InternetExplorerDriver.INTRODUCE_FLAKINESS_BY_IGNORING_SECURITY_DOMAINS, true);
            // 设置初始化浏览器地址
            capabilities.setCapability(InternetExplorerDriver.INITIAL_BROWSER_URL, "https://www.baidu.com");
            // 配置ie驱动位置
            System.setProperty("webdriver.ie.driver", "src/test/resources/IEDriverServer.exe");
            // 创建ie驱动对象
            driver = new InternetExplorerDriver();
        } else if ("firefox".equalsIgnoreCase(type)) {
            System.setProperty("webdriver.firefox.bin", "D:\\Mozilla Firefox\\firefox.exe");
            System.setProperty("webdriver.firefox.driver", "src/test/resources/geckodriver.exe");
            driver = new FirefoxDriver();
        }
        return driver;
    }
}

最后,绵薄之力

感谢每一个认真阅读我文章的人,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

 这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

资料获取方式:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/657059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何把在线K歌“玩起来”——专访撕歌音视频架构师程乐

编者按:在线K歌的业务已经发展了十年,程乐在音视频领域也闯荡了十年,甚至更久。为什么选择在线K歌领域?如何走过“漫长的季节”,迎来新的风景?如何在“在线K歌”这块难啃的骨头里分点肉?在这一连…

【存储】cache memory、primary memory and secondary memory

一、提要二、计算机的存储结构三、高速缓存:cache memory四、主存:Primary memory4.1 RAM4.11 SRAM 和 DRAM的概念4.12 SRAM 和 DRAM的应用场景 4.2 ROM4.21 PROM4.22 EPROM▶ EEPROM▶ UVEPROM 五、辅助存储器:secondary memory六、单片机的…

redis的4种模式,单机,哨兵、主从复制、集群

为了redis叫做redis服务器? 因为在运行时,在进行工作时是一个被注册一个进程(服务),我们把他叫做一个redis服务器。(就是个应用程序而已。) 1.单机模式 我们安装redi,启动服务之后,默认就这个,只有一个redis服务器(…

编译原理笔记(哈工大编译原理)(持续更新)

文章目录 前言概论语言与文法基本概念字母表串字母表与串的联系 文法语言推导和规约句型与句子语言与字母表 文法的分类CFG的分析树 前言 说实话,我不是很想上这门课,确实没什么大用,虽然我觉得这门课学一学也挺好,但是我觉得弄8…

架构师必备项目管理方法-关键路径法

在《架构思维的六要素》中提到成本、规划、需求、维护、人员和质量是要考量的留个维度。咱们在日常工作中多少都会接触一些相关的管理方法,但是似乎是不知道也不影响干活,所以很多人也没有去深究。但实际上很可能知道了做事就更能抓住重点。 关键路径法是…

预测神经胶质瘤基因型的多模态学习

文章目录 Multi-modal learning for predicting the genotype of glioma摘要本文方法多模态数据生成Brain networks construction via self-supervised NNsMulti-modal learning for image, geometrics and brain networksBi-level multi-modal contrastive loss Population gr…

html实现好看的个人介绍,个人主页模板3(附源码)

文章目录 1.设计来源1.1 主界面1.2 关于我界面1.3 教育成就界面1.4 项目演示界面1.5 联系我界面 2.效果和源码2.1 动态效果2.2 源代码2.2 源代码目录 源码下载 作者:xcLeigh 文章地址:https://blog.csdn.net/weixin_43151418/article/details/131263195 …

新手Maven入门(一)

Mavenue介绍和基本概念 一、什么是Maven1.1 Maven的组成1.2 安装和配置Maven1.2.1 下载1.2.2 安装 二、Maven 的基本概念2.1 标准的目录结构2.2 POM 大纲2.2.1 pom大纲展示 2.3 构件2.3.1 什么是maven的构建 2.4 POM 文件的用例2.5 GAV 坐标 三、依赖 一、什么是Maven Maven 是…

2023年前端面试汇总-计算机网络

1. HTTP协议 1.1. GET和POST的请求的区别 Post 和 Get 是 HTTP 请求的两种方法,其区别如下: 1. 应用场景 GET 请求是一个幂等的请求,一般 Get 请求用于对服务器资源不会产生影响的场景,比如说请求一个网页的资源。而 Post 不是…

如何在Ubuntu上安装MongoDB?

一、Ubuntu安装MongoDB MongoDB安装很简单,无需下载源文件,可以直接用apt-get命令进行安装。 打开终端,输入以下命令 sudo apt-get install mongodb这时装好以后应该会自动运行mongod程序,通过命令查看进程是否已经启动 pgrep …

Spring 实现AOP常见的两种方式(注解或者自定义注解)

第一种 导入AOP相关坐标(依赖冲突解决办法&#xff0c;将依赖中版本号删除&#xff0c;springboot会自动匹配合适的版本 ) <dependencies><!--spring核心依赖&#xff0c;会将spring-aop传递进来--><dependency><groupId>org.springframework</gr…

自动化测试必会之数据驱动测试

数据驱动测试 在实际的测试过程中&#xff0c;我们会发现好几组用例都是相同的操作步骤&#xff0c;只是测试数据的不同&#xff0c;而我们往往需要编写多次用例来进行测试&#xff0c;此时我们可以利用数据驱动测试来简化该种操作。 参数化&#xff1a; 输入数据的不同从而产…

C语言:输入两个升序排列的序列,将两个序列合并为一个有序序列并输出。

题目&#xff1a; 描述 输入两个升序排列的序列&#xff0c;将两个序列合并为一个有序序列并输出。 输入描述&#xff1a; 输入包含三行&#xff0c; 第一行包含两个正整数n, m&#xff0c;用空格分隔。n表示第二行第一个升序序列中数字的个数&#xff0c;m表示第三…

C++ 教程(12)——循环

C 循环 有的时候&#xff0c;可能需要多次执行同一块代码。一般情况下&#xff0c;语句是顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。 编程语言提供了允许更为复杂的执行路径的多种控制结构。 循环语句允许我们多次…

朋友圈功能合集来咯!定时发朋友圈,查看朋友圈,朋友圈跟圈,一键转发朋友圈,延迟评论

&#x1f30a;发布朋友圈 功能介绍&#xff1a;可使用已登录在系统上的微信号发送朋友圈。支持发送图片、文字、视频和公众号链接等几种类型的内容。 &#xff08;1)朋友圈内容编辑&#xff1a;可以在输入框中输入要发送的文本&#xff0c;并在浮窗中选择表情。上传图片可以点…

【c++11】c++11特性

c11 c11简介列表初始化std::initializer_list autodecltypenullptr 结语 c11简介 从C0x到C11&#xff0c;C标准10年磨一剑&#xff0c;第二个真正意义上的标准珊珊来迟。相比于C98/03&#xff0c;C11则带来了数量可观的变化&#xff0c;其中包含了约140个新特性&#xff0c;以…

QT QTreeView\QTreeWidget控件 使用详解

本文详细的介绍了QTreeView、QTreeWidget控件的各种操作&#xff0c;例如&#xff1a;新建界面、QTreeWidget、QTreeView、控件布局、设置列、设置宽高、设置列表头、设置复选框、设置图标、添加树、删除树、查找树、修改树、设置选中、树排序、事件、信号、槽函数、添加节点、…

【玩转Docker小鲸鱼叭】MacOS系统安装Docker

安装Docker Mac 系统安装 Docker 其实很简单&#xff0c;我们在官方文档下载安装一下就可以了&#xff0c;但是需要注意 Docker 官方建议 MacOS 必须是版本 11 或更高版本&#xff0c;如果版本较低&#xff0c;建议先升级 MacOS 版本。 可以通过左上角的小  图片查看系统版…

浅析Spring-kafka源码——消费者模型的实现

SpringBoot项目中的消费端实现而言,Spring-kafka没有用原生的ConsumerConnector,,而是借助原生client的拉取消息功能做了自己的消费模型的实现,提供了@KafkaListener注解这种方式实现消费。 开发中在使用Spring-kafka时,一般也都是通过使用@KafkaListener注解的方法来实现…

Android MPAndroidChart折线图渐变填充实现

效果如下&#xff1a; 以下是一个从上到下渐变的drawable&#xff0c;上面是蓝色&#xff0c;逐步向下变成白色&#xff1a; chart_bg.xml <?xml version"1.0" encoding"utf-8"?> <shape xmlns:android"http://schemas.android.com/apk…