【软件测试】基于博客系统的自动化测试

news2025/1/12 15:47:50

目录

1.我的博客系统链接

2.使用selenium对博客系统进行自动化测试

1.引入依赖

2.创建公共类

3.创建测试套件类

4.测试登陆界面

5. 测试博客列表页

6.测试写博客页面

7.测试删除博客

8.最终运行结果


1.我的博客系统链接

用户登录

2.使用selenium对博客系统进行自动化测试

1.引入依赖

创建一个maven项目,在pop.xml中引入以下依赖

    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.9.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.9.1</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.9.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.创建公共类

因为对每一个页面进行测试都需要创建浏览器驱动,所以我们可以把他提取出来并设置成静态的,就可以让创建和销毁驱动的操作只实现一次,其他类都继承这个类即可

package org.example.common;

import org.openqa.selenium.chrome.ChromeDriver;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

public class AutotestUtils {

    private static ChromeDriver driver;

    public static ChromeDriver createDrive() {
        if (driver == null) {
            driver = new ChromeDriver();
            // 显示等待, 渲染页面, 防止找不到页面元素
            driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
        }
        return driver;
    }
}

3.创建测试套件类

创建一个类,通过@Suite注解识别该类为测试套件类,使用@SelectClasses来注解声明我们要运行哪些类

package org.example.tests;

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({loginTest.class, BlogListTest.class, BlogEditTest.class})
public class RunSuite {

}

4.测试登陆界面

创建一个类继承AutTestUtils类得到浏览器驱动,然后开始测试

package org.example.tests;


import org.example.common.AutotestUtils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;

import static java.lang.Thread.sleep;


@TestMethodOrder(MethodOrderer.OrderAnnotation.class)// 按顺序执行
public class loginTest extends AutotestUtils {
    public static ChromeDriver driver = createDrive();

    /**
     * 打开网页
     */
    @Test
    @BeforeAll
    static void init() {
        // 跳转到登陆界面
        driver.get("http://8.130.122.250:8080/blog/blog_login.html");
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }

    /**
     * 检测登陆页面是否正常打开
     */
    @Test
    @Order(1)
    void loginPageTest() {
        // 显示等待
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        // 用断言判断用户登陆是否显示正确
        String expect = "用户登录";
        String actual = driver.findElement(By.cssSelector("body > div.login-container > form > div > div.title")).getText();
        Assertions.assertEquals(expect, actual);
        // 检查提交按钮是否存在
        driver.findElement(By.cssSelector("#btn_login_submit"));
    }

    /**
     * 异常登陆测试
     */
    @Order(2)
    @ParameterizedTest
    @CsvSource({"张三, 12346","李四, 1236"})
    public void loginAbnormal(String username, String password) throws InterruptedException {
        driver.get("http://8.130.122.250:8080/blog/blog_login.html");
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //清空用户名和密码框
        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("#btn_login_submit")).click();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

        // 与期望结果对比
        String expect = "用户名或密码不正确";
        // 强制等待
        sleep(2000);
        // 获取弹窗文本
        String actual = driver.switchTo().alert().getText();
        // 点击弹窗确认按钮
        driver.switchTo().alert().accept();
        Assertions.assertEquals(expect, actual);
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }

    /**
     * 正常登陆测试
     */
    @Order(3)
    @ParameterizedTest
    @CsvSource({"张三, 123456","李四, 123456"})
    public void loginNormalTest(String username, String password) {
        driver.get("http://8.130.122.250:8080/blog/blog_login.html");
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        //清空用户名和密码框
        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("#btn_login_submit")).click();
        driver.navigate().back();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }
}

5. 测试博客列表页

步骤同上

package org.example.tests;

import org.example.common.AutotestUtils;
import org.junit.jupiter.api.*;
import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;

import java.util.concurrent.TimeUnit;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogListTest extends AutotestUtils {

    // 获取驱动
    private static ChromeDriver driver = createDrive();

    /**
     * 打开网页
     */
    @BeforeAll
    public static void openWeb() {
        driver.get("http://8.130.122.250:8080/blog/blog_list.html");
    }

    /**
     * 测试博客列表显示是否正常
     */
    @Order(1)
    @Test
    void elementAppear() {
        driver.get("http://8.130.122.250:8080/blog/blog_list.html");
        // 判断登录用户为李四
        String actualUsername = driver.findElement(By.cssSelector("#h_list_username")).getText();
        String username = "李四";
        Assertions.assertEquals(actualUsername, username);
        // 判断标题不为空
        String title = driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.blog-title")).getText();
        Assertions.assertNotNull(title);
        // 判断登录url
        String url = "http://8.130.122.250:8080/blog/blog_list.html";
        String actualUrl = driver.getCurrentUrl();
        Assertions.assertEquals(url, actualUrl);
    }

    /**
     * 测试按钮
     */
    @Test
    @Order(2)
    public void buttonTest() {
        // 查看全文按钮测试
        driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.aEl > a")).click();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        driver.navigate().back();

    }
}

6.测试写博客页面

注释中有详细步骤

package org.example.tests;

import org.example.common.AutotestUtils;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.chrome.ChromeDriver;

import java.util.concurrent.TimeUnit;

import static java.lang.Thread.sleep;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogEditTest extends AutotestUtils {


    static ChromeDriver driver = createDrive();
    /**
     * 打开博客编辑页
     */
    @BeforeAll
    static void openWeb() {
        driver.get("http://8.130.122.250:8080/blog/blog_eidt.html");
    }

    /**
     * 错误发布测试
     */
    @Order(1)
    @ParameterizedTest
    @CsvSource({",正文"})
    void abnormalTest (String title, String content) throws InterruptedException {
        driver.get("http://8.130.122.250:8080/blog/blog_eidt.html");
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        // 输入测试
        ((JavascriptExecutor)driver).executeScript("document.querySelector(\"#title\").value="+title+"");
        driver.findElement(By.cssSelector("#submit")).click();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        // 等弹窗出现
        sleep(1000);
        // 点击弹窗
        driver.switchTo().alert().accept();
        driver.navigate().back();
    }

    /**
     * 正确发布测试
     */
    @Order(2)
    @Test
    void normalTest() throws InterruptedException {
        // 点击按钮
        driver.findElement(By.cssSelector("body > div.nav > div > div > a:nth-child(2)")).click();
        sleep(8000);
        // 输入标题与正文
        String title = "自动化测试最终版2";
        driver.findElement(By.cssSelector("#title")).sendKeys(title);
        // 编辑器无法输入,使用一个能写出来符号的按钮替代
        driver.findElement(By.cssSelector("#blog_edit > div.editormd-toolbar > div > ul > li:nth-child(5) > a > i")).click();
        sleep(1000);
        // 点击提交
        driver.findElement(By.cssSelector("#submit")).click();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        // 强制等待弹窗
        sleep(1000);
        // 点击弹窗,是否为发布成功
        String expect = "发布成功";
        String actual = driver.switchTo().alert().getText();
        driver.switchTo().alert().accept();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        // 查看跳转页面是否为博客列表界面
        String url = "http://8.130.122.250:8080/blog/blog_list.html";
        String actualUrl = driver.getCurrentUrl();
        Assertions.assertEquals(url, actualUrl);
        // 查看第一条博客标题是否为刚才所发
        String actualTitle = driver.findElement(By.cssSelector("body > div.container > div.container-right > div:nth-child(1) > div.blog-title")).getText();
        Assertions.assertEquals(title, actualTitle);
    }

    /**
     * 关闭浏览器
     */
    @AfterAll
    static void quit() {
        driver.quit();
    }
}

7.测试删除博客

因为删除博客的功能暂时没有完成,下次补上

8.最终运行结果

本篇博客就到这里啦!!我们下篇博客见~~

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

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

相关文章

网络安全(黑客)系统自学,成为一名白帽黑客

前言 黑客技能是一项非常复杂和专业的技能&#xff0c;需要广泛的计算机知识和网络安全知识。你可以参考下面一些学习步骤&#xff0c;系统自学网络安全。 在学习之前&#xff0c;要给自己定一个目标或者思考一下要达到一个什么样的水平&#xff0c;是学完找工作&#xff08;…

学习笔记22 map

一、概论 map的每个元素都由两个部分组成&#xff1a;键和值。每个键都与一个特定的值相关联&#xff0c;并且可以用于定位该值。 map和set很像&#xff0c;只不过map存储的是key&#xff0c;由key再映射到value&#xff0c;而set存储的就是value本身。 Map接口是泛型的&…

拦截Bean使用之前各个时机的Spring组件

拦截Bean使用之前各个时机的Spring组件 之前使用过的BeanPostProcessor就是在Bean实例化之后&#xff0c;注入属性值之前的时机。 Spring Bean的生命周期本次演示的是在Bean实例化之前的时机&#xff0c;使用BeanFactoryPostProcessor进行验证&#xff0c;以及在加载Bean之前进…

flink to starrocks 问题集锦....

[问题排查]导入失败相关 - 问题排查 - StarRocks中文社区论坛 starrocks官网如下&#xff1a; Search StarRocks Docs starrocks内存配置项&#xff1a; 管理内存 Memory_management StarRocks Docs 问题1&#xff1a;实时写入starrocks &#xff0c;配置参数设置如下&a…

【【51单片机11.0592晶振红外遥控】】

51单片机11.0592晶振红外遥控 红外遥控&#xff0c;51单片机完结 这是初步实现的架构 怎么实现内部的详细逻辑 我们用状态机的方法 0状态时一个空闲状态 当它接收到下降沿开始计时然后转为1状态 1状态下 寻找start 或者repeat的信号 再来下降沿读出定时器的值 如果是start 那…

华为eNSP:isis的配置

一、拓扑图 二、路由器的配置 配置接口IP AR1&#xff1a; <Huawei>system-view [Huawei]int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 1.1.1.1 24 [Huawei-GigabitEthernet0/0/0]qu AR2: <Huawei>system-view [Huawei]int g0/0/0 [Huawei-GigabitEthe…

【沁恒蓝牙mesh】数据收发接口与应用层模型传递

本文主要描述了沁恒蓝牙mesh SDK的蓝牙数据收发接口&#xff0c;以及应用层的回调函数解析以及模型传递 这里写目录标题 1. 数据收发接口1.1【发送数据】1.2 【数据接收】 2. 应用层模型分析 1. 数据收发接口 1.1【发送数据】 /*&#xff08;1&#xff09;接口1 */ /*接口一&…

力扣热门100题之最大子数组和【中等】【动态规划】

题目描述 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组 是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] 输出&a…

Java文字转语音功能实现

需要下载jacob-1.18&#xff0c;网上一堆 项目中引入pom文件 <!-- https://mvnrepository.com/artifact/com.jacob/jacob 文字转语音 --> <dependency><groupId>com.hynnet</groupId><artifactId>jacob</artifactId><version>1.18&…

Go语言中‘String’包中的‘Cut‘函数的实现

Go语言中‘String’包中的’Cut’函数的实现 ​ Cut函数用于在字符串**‘s’中查找子串’sep’&#xff0c;并将字符串’s’在子串 ‘sep’ 第一次出现的位置分割成两部分&#xff1a;before和after** package main import("fmt" "strings" ) func main(…

Python初学

认识计算机&#xff1a; 计算机是怎么构成的——冯诺依曼体系结构 内存外存的区别&#xff1a; 一般机械硬盘的存储数据的期限是&#xff1a;几年到十几年 什么是编程&#xff1f; 制作软件——编程/软件开发 编程语言有哪些&#xff1f; Python Python背景知识 荷兰人Guid…

M5ATOMS3基础02传感器MPU6886

M5ATOMS3基础01按键 简洁版本 MPU6886是一款6轴IMU单元&#xff0c;具有3轴重力加速度计和3轴陀螺仪。它采用16位ADC&#xff0c;内置可编程数字滤波器和片上温度传感器&#xff0c;并通过I2C接口&#xff08;地址为0x68&#xff09;与上位机通信。MPU6886支持低功耗模式&#…

Linux系统MySQL中用户的权限管理

本节主要学习用户权限管理的概述&#xff0c;用户权限类型&#xff0c;用户赋权&#xff0c;权限删除&#xff0c;用户删除等。 目录 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、用户删除 一、概述 数据库用户权限管理是数据库系统中非常重要的一个方面&am…

如何理解 SpringBoot 的生命周期

生命周期&#xff0c;就是从诞生到死亡的一个过程。Spring 中 bean 也是如此。在 Spring 中的 ConfigurableApplicationContext 的 refresh 开始直到一个 bean 可以被正常使用&#xff0c;中间经历了一系列初始化操作&#xff1b;而在其 close 后又经历了一系列销毁操作&#x…

(八九)如何与InfluxDB交互InfluxDB HTTP API

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 8 章 前言&#xff1a;如何与InfluxDB交互 1、InfluxDB启动后&#xff0c;会向外提供一套HTTP API。外部程…

配置代理——解决跨域问题(详解)

之前写项目的时候总会遇到配置代理的问题&#xff0c;可是配置了之后有时有用&#xff0c;有时就没有用&#xff0c;自己之前学的也是懵懵懂懂&#xff0c;于是专门花了一个小时去了解了如何配置代理跨域&#xff0c;然后在此记录一下&#xff0c;方便自己以后查阅。 一、 常用…

自守数 C语言实现

自守数 描述 自守数是指一个数的平方的尾数等于该数自身的自然数。例如&#xff1a;25^2 625&#xff0c;76^2 5776&#xff0c;9376^2 87909376。请求出n(包括n)以内的自守数的个数 数据范围&#xff1a; 1≤n≤10000 输入描述&#xff1a; int型整数 输出描述&#xf…

重学C++系列之多态

一、什么是多态 多态是类的三大特性之一&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;。多态是指由继承而产生的相关不同的类&#xff0c;其派生类对象对同一个消息会作出不同响应。 二、引入多态的目的 能增加程序的灵活性&#xff0c;可以减轻系统升级和维…

EC200U-CN学习(三)

EC200U系列内置丰富的网络协议&#xff0c;集成多个工业标准接口&#xff0c;并支持多种驱动和软件功能&#xff08;适用于Windows 7/8/8.1/10、Linux和Android等操作系统下的USB驱动&#xff09;&#xff0c;极大地拓展了其在M2M领域的应用范围&#xff0c;如POS、POC、ETC、共…

TCP协议如何实现可靠传输

TCP最主要的特点 TCP是面向连接的运输层协议&#xff0c;在无连接的、不可靠的IP网络服务基础之上提供可靠交付的服务。为此&#xff0c;在IP的数据报服务基础之上&#xff0c;增加了保证可靠性的一系列措施。 TCP最主要的特点&#xff1a; TCP是面向连接的输出层协议 每一条…