针对博客项目进行web自动化测试

2023-11-15

项目功能

  • 背景:当你在学习的时候,相信你一定有做笔记的经历,这是一个好习惯,方便你在遗忘或是复习的时候回顾知识,而接下来我要讲的这个程序,就可以方便你去写自己的学习笔记,并且可以发表出来,既方便自己学习,同时也可以分享给别人~

测试计划

功能测试

编写测试用例

在这里插入图片描述

使用Selenium+Junit5进行Web自动化测试

创建测试套件类

  • 创建一个类(自定义名为runSuite),通过 @Suite 注解标识该类为测试套件类(不是测试类),然后使用 @SelectClasses 注解来声明我们要指定的类(通过这个类来运行测试用例),这样优点如下:
  1. 相比于一个一个类来实例化,然后调用函数(测试用例)进行测试就大大减少了开销和时间;
  2. 同时指定了类的测试顺序,即在注解@SelectClasses参数中的类测试顺序为从左向右;
@Suite
@SelectClasses({BlogLoginTest.class, DriveQuitTest.class})

public class runSuite {

}

博客登录页

  • 登录页面正常加载(检查元素是否存在)
  • 登录成功(检查跳转页面元素是否存在)
  • 登录失败
  • 使用注解声@TestMethodOrder(MethodOrderer.OrderAnnotation.class)+@Order(1)声明执行顺序
  • @BeforeAll 表示当前方法需要在当前类下所有用例执行之前执行一次,并且被该注解修饰的方法必须是静态方法
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogLoginTest  extends AutotestUtils{

    public static EdgeDriver driver = createDriver();
    //如果要测试登录页面,以下所有的用例都有一个共同的步骤
    //1.要有浏览器对象 2.访问登录页面的url,因此加一个注解
    @BeforeAll
    static void baseControl(){
        driver.get("http://localhost:8080/login.html");
    }

    /**
     * 检查登录页面正常显示
     * 检查点:(主页,注册 )元素是否存在
     */

    @Test
    @Order(1)
    void loginPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));//主页
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)"));//注册
        getScreenShot(getClass().getName());
    }
    /**
     * 页面登录成功
     * @param username
     * @param password
     */
    @ParameterizedTest
    @CsvSource({"admin,123456"})
    @Order(2)
    void loginSuc(String username,String password) throws IOException, InterruptedException {
        driver.findElement(By.cssSelector("#username")).clear();//再次测试的时候,先将上次的用户名,密码清空
        driver.findElement(By.cssSelector("#password")).clear();

        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        driver.findElement(By.cssSelector("#submit")).click();
        //登录成功,页面跳转至博客列表页,然后可以找到博客列表页的特殊元素,说明登录成功
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)"));//(创作)

        getScreenShot(getClass().getName());
       // driver.navigate().back();//跳转至列表页需要返回才能再次测试登录页面

    }
    /**
     *1.登录失败
     */
    @ParameterizedTest//参数化方法
    @CsvSource({"admin,1234","lisi,123456"})//多参数
    @Order(3)
    void loginFail(String username,String password) throws IOException, InterruptedException {
      driver.findElement(By.cssSelector("#username")).clear();//再次测试的时候,先将上次的用户名,密码清空
       driver.findElement(By.cssSelector("#password")).clear();
       driver.findElement(By.cssSelector("#username")).sendKeys(username);
       driver.findElement(By.cssSelector("#password")).sendKeys(password);
       driver.findElement(By.cssSelector("#submit")).click();
            //登录失败,弹窗提示“用户名或密码错误”
        Thread.sleep(5000);
        Alert alert = driver.switchTo().alert();//切换到弹窗
        alert.accept();//确认
        getScreenShot(getClass().getName());
        driver.navigate().refresh();
        Thread.sleep(5000);

        }
}

博客列表页(主页)

public class BlogListTest extends AutotestUtils {
    public static EdgeDriver driver = createDriver();
    @BeforeAll
    static void baseControl(){
        driver.get("http://127.0.0.1:8080/blog_list.html");
    }
    @Test
    void BlogListLoadRight(){
        driver.findElement(By.cssSelector("body > div.container > div > div.blog-pagnation-wrapper > button:nth-child(1)"));//首页
    }
}

博客详情页

public class BlogDetailTest extends AutotestUtils {
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl(){
        driver.get("http://localhost:8080/blog_content.html?id=2");
    }
    @Test
    void  editPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("#title"));
        driver.findElement(By.cssSelector("body > div.container > div.container-right > div > div.date"));
        driver.findElement(By.xpath("//*[@id=\"title\"]"));
    }
}

个人博客列表页

public class BlogListTest extends AutotestUtils {
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl(){
        driver.get("http://localhost:8080/myblog_list.html");
    }
    /**
     * 检查列表页面正常显示
     */
    @Test
    void  listPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)"));//退出登录
        driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(2) > div:nth-child(4) > a:nth-child(2)"));//修改
        getScreenShot(getClass().getName());
    }
}

修改密码页

  • 有2个弹窗,必须添加强制等待(目前没有想到更好的办法)
 driver.findElement(By.xpath("/html/body/div[1]/a[4]")).click();//修改密码

        driver.findElement(By.cssSelector("#password")).sendKeys("admin");
        driver.findElement(By.cssSelector("#password1")).sendKeys("123456");
        driver.findElement(By.cssSelector("#password2")).sendKeys("123456");
        driver.findElement(By.cssSelector("#submit")).click();
        
        Thread.sleep(5000);

        Alert alert  = driver.switchTo().alert();
        Thread.sleep(5000);
        alert.accept();
        Thread.sleep(5000);

        alert.accept();
        Thread.sleep(5000);

        String actual = driver.findElement(By.cssSelector("body > div.login-container > div > h3")).getText();
        String expect = "登录";
        Assertions.assertEquals(expect,actual);

编辑博客页

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogEditTest extends AutotestUtils {
    public static EdgeDriver driver = createDriver();

    @BeforeAll
    static void baseControl(){
        driver.get("http://localhost:8080/blog_edit.html");
    }
    /**
     * 检查编辑页面正常显示
     */
    @Test
    @Order(1)
    void  editPageLoadRight() throws IOException {
        driver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)"));//我的博客
        driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button"));//发布文章
        getScreenShot(getClass().getName());
    }

   //这个没通过,因为新添加的文章是往后添加的,不是第一篇
    @ParameterizedTest
    @CsvSource("自动化测试")
    @Order(2)
    void editAndSubmit(String title,String content) throws IOException, InterruptedException {
        String expect = title;
        driver.findElement(By.cssSelector("#title")).sendKeys(expect);
        driver.findElement(By.cssSelector("#editorDiv > div.editormd-toolbar > div > ul > li:nth-child(17) > a > i")).click();//H6
        driver.findElement(By.xpath("/html/body/div[2]/div[1]/button[1]")).click();//发布文章
        
        getScreenShot(getClass().getName());
        String actual = driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > div.title")).getText();
        Assertions.assertEquals(expect,actual);
    }
}

退出驱动

  • 测试登录,驱动退出,然后创建驱动,测试编辑页,驱动退出
  • 浪费资源和时间,拖慢测试进程
  • 编写一个独立的退出类,在所有测试完成后,退出驱动
public class DriveQuitTest extends AutotestUtils {
    public static EdgeDriver driver = createDriver();
    @Test
    void driveQuit(){
        driver.quit();
    }
}

屏幕截图

  • 有的时候测试用例执行出错了,需要查看当时网页出现的情况,那么就需要使用屏幕截图来排查问题
 public List<String> getTime(){
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");
        SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd");//年月日

        String filename = sim1.format(System.currentTimeMillis());//生成的图片名
        String dirname = sim2.format(System.currentTimeMillis());//文件夹的名字
        List<String> list = new ArrayList<>();
        list.add(dirname);
        list.add(filename);
        return list;
    }
    public void getScreenShot(String str) throws IOException {
        List<String> list = getTime();
        // ./是当前项目路径下
        String filename = "./src/test/java/com/blog/test/"+list.get(0)+"/"+ str +"/"+list.get(1)+".png";//路径文件名
        File srcfile = driver.getScreenshotAs(OutputType.FILE);//srcfile 是 生成的屏幕截图
        FileUtils.copyFile(srcfile,new File(filename));//将 srcfile 放到指定的文件夹下
    }

测试有什么亮点

  • 使用selinium4自动化测试工具和junit5单元测试框架结合

  • 使用了junit5中提供的注解@Test,避免生成过多的对象,造成资源和时间的浪费,提高了自动化的执行效率

  • 只创建一次驱动,避免每个用例重复创建驱动对象造成时间的浪费

  • 使用注解@ParameterizedTest参数化:保持用例的简洁,提高代码的可读性

  • 注解@Suite测试套件:降低了测试人员的工作量,通过套件一次执行所有的测试用例

  • 使用等待:提高了自动化运行效率,提高了自动化的稳定性

  • 屏幕截图:有的Bug不能复现,方便问题的追溯和解决

自动化测试发现bug的多少

  • 就我的一个小项目来说,发现的bug并不多,因为自动化测试做的是一些相对稳定的功能【回归测试】,在前面的项目版本中,已经将bug修复,所以说,发现的bug并不多~

遇到过哪些异常

  • NoSuchElementException:没有该元素异常
    1.是否 selinium 没有定位到元素
  • TimeoutException : 超时异常
  • ElementNotVisibleException :元素不可见异常
  • 产生弹窗,隐式等待不生效,需添加显示等待
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

针对博客项目进行web自动化测试 的相关文章

随机推荐

  • 直播预告

    12月26日 RTSCon2021开发者沙龙将在线上举办 拍乐云Pano受邀出席 服务端专家沈伟锋将在活动中带来关于 拍乐云融合语音通话技术实践 的主题演讲 RTSCon的前身是FreeSWITCH开发者沙龙 而RTS的全称是Real Ti
  • (十三):图

    1 图的基本介绍 1 1为什么要有图 前面我们学到了线性表和树 线性表局限于直接前驱和一个直接后继结点的关系 树也只能有一个直接前驱也就是父节点 当我们需要多对多关系时候 就需要图 1 2图的举例说明 图是一种数据结构 其中结点可以具有零个
  • SpringBoot优质开源项目分享

    Spring Boot 算是目前 Java 领域最火的技术栈了 也是Java开发人员不得不掌握的技术 今天给大家整理了13个优质 Spring Boot 开源项目给大家参考 希望能够帮助到正在学习 Spring Boot 的小伙伴 小伙伴简
  • RK3568资料汇总

    文档资料 野火 https doc embedfire com products link zh latest linux ebf lubancat html 正点原子 http 47 111 11 73 docs boards arm l
  • python的判断与循环语句

    一 判断语句 1 判断 在程序中如果某些条件满足 才能做某件事情 而不满足时不允许做 这就是所谓的判断 2 if语句的使用格式 if 要判断的条件 条件成立时 要做的事情 如 判断年纪 如果 age 大于 18 输入成年 age 18 if
  • Centos7 交叉编译QT5.9.9源码 AArch64架构

    环境准备 centos7 镜像 下载地址 http mirrors aliyun com centos 7 9 2009 isos x86 64 aarch64交叉编译链 下载地址 https releases linaro org com
  • Java与代码检查与自动化测试

    Java是一种面向对象的编程语言 具有简单 快速 安全 可靠等特点 在Java编程中 代码质量的好坏直接关系到最终软件的质量 为了确保代码质量 我们需要进行代码检查和自动化测试 本文将详细介绍Java代码检查和自动化测试的概念 原则 工具及
  • 【DRAM存储器五】DRAM存储器的架构演进-part2

    个人主页 highman110 作者简介 一名硬件工程师 持续学习 不断记录 保持思考 输出干货内容 参考书籍 Memory Systems Cache DRAM Disk 目录
  • TCP的粘包问题

    TCP transport control protocol 传输控制协议 是面向连接的 面向流的 提供高可靠性服务 收发两端 客户端和服务器端 都要有一一成对的socket 因此 发送端为了将多个发往接收端的包 更有效的发到对方 使用了优
  • python pyinstaller打包参数介绍(转)

    pyinstaller相关参数 F onefile 打包一个单个文件 如果你的代码都写在一个 py文件的话 可以用这个 如果是多个 py文件就别用 D onedir 打包多个文件 在dist中生成很多依赖文件 适合以框架形式编写工具代码 我
  • 如何使用yum安装最新软件包

    分享请标明来自 https www css3 io how yum install release soft html 背景 使用yum安装软件时 会经常遇到安装的软件是老版本的 被非自己期望的release版本 这到底是怎么回事儿 得从r
  • 【2023】java通过modbus4j实现modus TCP通讯

    Modbus通信协议 主要分为三个子协议 RTU ASCII TCP Modbus RTU 传输的是字节数组 bit 通信 读写 输出 可以读写 输入 只能读 存储区 输出线圈 输入线圈 输出寄存器 输入寄存器 线圈 代表一个布尔量 最小单
  • Docker环境安装

    Docker环境安装 Docker简介 Docker工作原理 Docker的应用场景 Docker 的优点 CentOS Docker 安装与配置 Docker 安装 Docker 配置 Docker容器概念 Docker容器操作 拉取镜像
  • Java 实现文件复制及文件夹复制

    在Java中 有多种方法可以实现文件的复制 以下是几种常用的方式 使用字节流进行复制 通过FileInputStream和FileOutputStream分别创建源文件和目标文件的输入输出流 然后通过循环读取源文件内容 并将数据写入目标文件
  • mysql相加并输出_用shell把执行的两条sql语句相加并输出数据库名和相加的值以tab健隔开...

    SELECT SUM PresentSum FROM Lg ConsumeDetail0 WHERE ConsumeDate lt 2016 11 01 AND OpId 300 SELECT SUM PresentSum FROM Lg
  • vcpu和physical cpu 绑定

    参考libvirt中xml的写法可以将vpu和物理cpu 绑定 https libvirt org formatdomain html elementsCPUTuning
  • Unity鼠标光标使用学习

    Unity下的鼠标光标程序相关的就一个类下的2 3个方法 首先 光标导入图片的设置需要将类型设置为Cursor 设置鼠标光标的方法就一个 SetCursor 第一个参数是图片 第二个参数是点击点的偏移量 第三个参数是类型 public Te
  • Apollo配置中心Client源码学习(二)-- 配置同步

    上一篇文章 https blog csdn net crystonesc article details 106630412 我们从Apollo社区给出的DEMO开始逐步分析了Apollo客户端配置的创建过程 作为Apollo配置中心Cli
  • Javascript和CSS的标签属性对应表

    在写javascript中 经常要用到style对象的css属性 很多不记得 其实很好记 基本就是CSS中的 转化为javascript的驼峰写法 除了注意下float 盒子标签和属性对照 CSS语法 不区分大小写 JavaScript语法
  • 针对博客项目进行web自动化测试

    web自动化测试针对博客项目 项目功能 测试计划 功能测试 编写测试用例 使用Selenium Junit5进行Web自动化测试 创建测试套件类 博客登录页 博客列表页 主页 博客详情页 个人博客列表页 修改密码页 编辑博客页 退出驱动 屏