基于学习交流社区的自动化测试实现

一 项目介绍


项目名称

项目展示链接: 学习交流社区

项目介绍

项目介绍: 学习交流社区是一个基于Spring的前后端分离的在线论坛系统。使用了MySQL数据库来存储相关信息,项目完成后使用Xshell将其部署到云服务器上。
前端页面: 前端共由八个页面构成:注册页面,登录页面,首页,编辑帖子页面,帖子列表页面,个人中心页面,修改个人信息页面,帖子详情页面。
项目总结: 该项目可以实现通过发布帖子分享技术,并通过别人发布的帖子学习知识来进行技术交流,所以也可称之为技术交流社区。

项目功能

学习交流社区主要实现了以下功能 :

用户注册,用户登录,编辑帖子,删除帖子,查看帖子,点赞帖子,站内信,编辑个人信息等功能。


二 测试用例设计和功能测试


1.测试用例设计

测试用例会从界面测试,功能测试,性能测试,易用性测试,安全性测试,兼容性测试六个方面进行设计。

①登录页面

②注册页面

③首页

④发布帖子页面

⑤修改个人信息页面

2.功能测试环境

测试环境: win11
项目运行: CentOS,maven,JDK1.8
浏览器: Chrome浏览器

3.实际执行功能测试的部分操作

①登录页面

页面展示

给定一个正确的账号密码:
用户名 :锦鲤
密码:123456

操作

输入用户名 输入密码 操作 预期结果 实际结果
空 空 点击登录 提示用户名不能为空,密码不能为空 提示用户名不能为空,密码不能为空
张三(错误的用户名) 空 点击登录 提示用户名或密码错误 提示用户名或密码错误
锦鲤(正确的用户名) 空 点击登录 提示密码不能为空 提示密码不能为空
锦鲤(正确的用户名) 123(错误的密码) 点击登录 提示用户名或密码错误 提示用户名或密码错误
锦鲤(正确的用户名) 123456(正确的密码) 点击登录 登录成功 成功登录

②注册页面

页面展示

操作

输入用户名 输入昵称 输入密码 输入确认密码 勾选同意条款 点击注册 预期结果 实际结果
空 空 空 空 不勾选 点击注册 提示都不能为空 每个输入框下面都提示不能为空
张三 空 空 空 不勾选 点击注册 提示除用户名外都不能为空 其余三个输入框下面提示不能为空
张三 张三 111 123 勾选 点击注册 提示密码和确认密码不相同 提示请检查确认密码
张三 张三 111 111 不勾选 点击注册 提示请勾选 勾选框标红,点击注册按钮无结果
张三 张三 111 111 勾选 点击注册 注册成功 注册成功,跳转到登录页面,弹出是否要保存密码框

③首页

页面展示


操作

操作 预期结果 实际结果
点击Java 跳转至Java版块 跳转至Java版块
点击发布帖子 跳转至发布帖子页面 跳转至发布帖子页面
点击"任一帖子标题" 跳转至帖子详情页 跳转至帖子详情页
点击月亮标志 切换为夜晚模式 切换为夜晚模式
点击铃铛标志 显示所有私信 显示所有私信

④发布帖子页面

页面展示

操作

输入标题 输入内容 操作 预期结果 实际结果
空 空 点击发布 提示请输入帖子标题 提示请输入帖子标题
测试标题 空 点击发布 提示请输入帖子内容 提示请输入帖子内容
测试标题 测试内容 点击发布 发布成功 发布成功,跳转至首页

⑤修改个人信息页面

页面展示

操作

操作 预期结果 实际结果
点击修改头像,上传头像 头像变为刚刚上传的图片 图片无变化(上传图片功能还未实现)
输入邮箱地址,点击修改 修改成功 修改成功
输入电话号码,点击修改 修改成功 修改成功
输入错误原密码,点击提交修改 提示密码校验失败 提示密码校验失败
输入正确原密码,点击提交修改 修改成功 修改成功

三 接口测试


接口测试使用了:

  1. Junit单元测试
  2. Springfox Swagger 生成 API,完成 API 单元测试

1.Junit单元测试

单元测试类:

这里只列举用户接口和帖子接口的单元测试,其余类似

①用户接口

这里列举了注册,登录和修改个人信息的测试代码。

注册方法测试:

java 复制代码
    @Test
    @Transactional
    void createNormalUser() {
        // 构造User对象
        User user = new User();
        user.setUsername("boy1");
        user.setNickname("boy");

        // 定义一个原始的密码
        String password = "123456";
        // 生成盐
        String salt = UUIDUtil.UUID_32();
        // 生成密码的密文
        String ciphertext = MD5Util.md5Salt(password, salt);
        // 设置加密后的密码
        user.setPassword(ciphertext);
        // 设置盐
        user.setSalt(salt);
        // 调用Service层的方法
        userService.createNormalUser(user);
        // 打印结果
        System.out.println(user);
    }

修改个人信息测试:

java 复制代码
    @Test
    @Transactional
    void modifyInfo() {
        User user = new User();
        user.setId(3l); // 用户Id
        user.setUsername("testUser"); // 登录名
        user.setNickname("testUser1"); // 昵称
        user.setGender(null); // 性别
        user.setEmail("qqq@qq.com");// 邮箱
        user.setPhoneNum("15366668888"); // 电话
        user.setRemark("测试"); // 个人简介
        // 调用Service
        userService.modifyInfo(user);
    }

登录测试:

java 复制代码
    @Test
    void login() {
        User user = userService.login("bitboy", "123456");
        System.out.println(user);
    }

②帖子接口

这里列举了发布帖子,查询所有帖子列表,删除帖子,点赞帖子的测试代码。

发布帖子测试:

java 复制代码
    @Test
    @Transactional
    void create() {
        Article article = new Article();
        article.setUserId(2L); // boy
        article.setBoardId(1L); // java版块
        article.setTitle("单元测试");
        article.setContent("测试内容");
        articleService.create(article);
        System.out.println("发贴成功");
    }

查询所有帖子列表:

java 复制代码
    @Test
    void selectAll() throws JsonProcessingException {
        // 调用Service
        List<Article> articles = articleService.selectAll();
        // 转换成JSON字符串并且打印
        System.out.println(objectMapper.writeValueAsString(articles));
    }

点赞帖子和删除帖子方法测试:

java 复制代码
    @Test
    @Transactional
    void thumbsUpById() {
        articleService.thumbsUpById(1L);
        System.out.println("点赞成功");
    }

    @Test
    @Transactional
    void deleteById() {
        articleService.deleteById(11l);
        System.out.println("删除成功");
    }

2.Swagger API测试

测试链接:学习交流社区

接口测试版块总览:

回复接口:

帖子接口:

版块接口:

用户接口:

站内信接口:

⭐⭐⭐这里每个接口展示一个功能的测试过程。

①用户接口

功能:用户登录
账号:锦鲤

密码:123456

测试过程:

结果:登录成功

①帖子接口

功能:获取用户列子列表
输入用户id:1

测试过程:

结果:获取成功,用户id为1的用户共发布一篇文章

①回复接口

功能:发布回复
输入发布回复的帖子id:19

输入回复内容:支持好文!!!

过程:

结果:回复成功

①版块接口

功能:获取首页版块列表

过程:直接点击Execute

结果:操作成功

①站内信接口

功能:发送站内信
输入接收用户id:2

输入内容:你好

过程:

结果:操作成功

四 自动化测试


1.使用selenium进行自动化测试准备工作

1.引入依赖

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

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.创建公共类

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

java 复制代码
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来注解声明我们要运行哪些类

java 复制代码
package org.example.tests;

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

/**
 * 2023/8/21
 * 测试套件类
 */
@Suite
@SelectClasses({loginTest.class, IndexTest.class})
public class RunSuite {
}

2.对登录页面进行自动化测试

①打开登陆网页

②对登陆页面上的文字进行判断

  1. 页面上的用户名,密码,登录按钮是否都正常显示
  2. 点击去注册按钮能否正常跳转页面

③测试窗口伸缩

测试窗口缩小至指定大小,放大到最大

④错误的登录测试

  1. 用户名为空,提示用户名不能为空
  2. 密码为空,提示密码不能为空
  3. 用户名密码不匹配,提示用户名或密码错误

⑤正确的登录测试

输入正确的用户名与密码,登陆成功,跳转至首页,判断跳转的url是否正确,以及跳转页面上的文字是否显示正确

⑥运行结果

测试全部通过

※这里给出一个页面的详细代码,其他页面都与之类似

java 复制代码
package org.example.tests;

import org.example.common.AutotestUtil;
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.Dimension;
import org.openqa.selenium.chrome.ChromeDriver;

import java.util.concurrent.TimeUnit;

/**
 * wangcong
 * 2023/8/21
 * 登陆页面测试
 */
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class loginTest extends AutotestUtil {
    // 获取浏览器驱动
    public static ChromeDriver driver = createDrive();

    /**
     * 打开网页
     */
    @Test
    @BeforeAll
    static void init() {
        // 跳转到登录页面
        driver.get("http://47.109.128.149:6060/sign-in.html");
        // 隐式等待页面加载完成
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    }

    /**
     * 对登陆页面的一些文字显示进行判断
     */
    @Test
    @Order(1)
    void loginPageTest() {
        // 检查系统名称
        String expect = "用户登录";
        String actual = driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2")).getText();
        Assertions.assertEquals(expect, actual);
        // 判断登录窗口的内容
        String expect2 = driver.findElement(By.cssSelector("#signInForm > div.mb-3 > label")).getText();
        Assertions.assertEquals(expect2, "用户名");
        String expect3 = driver.findElement(By.cssSelector("#signInForm > div.mb-2 > label")).getText();
        Assertions.assertEquals(expect3, "密码");
        // 检查登陆按钮是否存在
        driver.findElement(By.cssSelector("#submit"));
        // 检查注册按钮是否存在
        driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a"));
        // 点击注册按钮
        driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click();
        // 判断跳转页面是否正确
        String url = driver.getCurrentUrl();
        Assertions.assertEquals(url, "http://47.109.128.149:6060/sign-up.html");
    }

    /**
     * 测试窗口伸缩
     */
    @Test
    @Order(2)
    public void windowSize() {
        driver.manage().window().setSize(new Dimension(900, 900));
        driver.manage().window().setSize(new Dimension(300, 300));
        driver.manage().window().maximize();
    }

    /**
     * 错误登录测试1
     */
    @ParameterizedTest
    @Order(4)
    @CsvSource(value = {"锦鲤, 12345"})
    void loginAbnormal1(String username, String password) {
        // 清空用户名和密码
        driver.findElement(By.cssSelector("#username")).clear();
        driver.findElement(By.cssSelector("#password")).clear();
        // 用户名为空
        driver.findElement(By.cssSelector("#username")).click();
        driver.findElement(By.cssSelector("#password")).sendKeys(password);
        String expect = driver.findElement(By.cssSelector("#signInForm > div.mb-3 > div")).getText();
        // 断言
        Assertions.assertEquals(expect, "用户名不能为空");
        // 密码为空
        driver.findElement(By.cssSelector("#username")).sendKeys(username);
        driver.findElement(By.cssSelector("#password")).clear();
        String expectPass = driver.findElement(By.cssSelector("#signInForm > div.mb-2 > div > div")).getText();
        // 断言
        Assertions.assertEquals(expectPass, "密码不能为空");
        // 返回上一个页面
//        driver.navigate().back();// 这里不需要返回,并未跳转页面
    }
    /**
     * 错误登录测试2
     */
    @ParameterizedTest
    @Order(4)
    @CsvSource(value = {"锦鲤, 12345","锦鲤呀,123456"})
    void loginAbnormal2(String username, String password) {
        // 清空用户名和密码
        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.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        // 判断弹窗内容
        String expect = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();
        // 断言
        Assertions.assertEquals(expect, "警告");
        // 返回上一个页面
//        driver.navigate().back();// 这里不需要返回,并未跳转页面
    }

    /**
     * 正确登录测试
     */
    @ParameterizedTest
    @Order(4)
    @CsvSource(value = {"小金, 123456","锦鲤, 123456"})
    void loginNormal(String username, String password) {
        // 清空用户名和密码
        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.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        // 判断跳转页面url
        String url = driver.getCurrentUrl();
        // 断言url
        Assertions.assertEquals(url, "http://47.109.128.149:6060/sign-in.html");
        // 判断显示是否为首页
        String expect = driver.findElement(By.cssSelector("#article_list_board_title")).getText();
        // 断言
        Assertions.assertEquals(expect, "首页");
        // 返回上一个页面
        driver.navigate().back();// 这里不需要返回,并未跳转页面
    }


}

3.对注册页面进行自动化测试

①打开注册页面

②对注册页面上的文字进行判断

  1. 判断用户注册,用户名,昵称,密码,确认密码,同意文字是否存在
  2. 注册按钮是否存在
  3. 登陆的超链接是否存在

④错误的注册测试

  1. 用户名,昵称,密码,确认密码,同意隐私政策,其中有任何一个不填写,注册失败

⑤正确的注册测试

  1. 用户名,昵称,密码,确认密码,同意隐私政策,所有都正确填写,注册成功
  2. 注册成功后,跳转到登陆界面

3.对首页进行自动化测试

①打开注册页面


相关推荐
daidaidaiyu3 小时前
ThingsBoard 集群的核心逻辑源码分析
java
我可能是个假开发4 小时前
FTP Unicode 文件名导致 `550` 的问题分析与解决方案
java·开发语言·spring
caoerzhong4 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
【JAVA】玩家5 小时前
Spring核心原理全解析:从零到生产实战
java·后端·spring
Wang's Blog5 小时前
Java框架 SpringCloud 快速入门: 实现 Feign 最佳实践(抽取方式)
java·spring cloud
MandalaO_O6 小时前
IDEA 开发(快捷键 + 调试 + 序列化)
java·ide·intellij-idea
xiaoqiMikko7 小时前
JVM 线上排查实战(七):jps 看不见它、jstack 连不上它,可它明明活得好好的
java·jvm
狼爷8 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言
念何架构之路8 小时前
zap扩展生态与总结
java·前端·数据库
第七页独白8 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库