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

一 项目介绍


项目名称

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

项目介绍

项目介绍: 学习交流社区是一个基于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.对首页进行自动化测试

①打开注册页面


相关推荐
陈大爷(有低保)10 分钟前
UDP Socket聊天室(Java)
java·网络协议·udp
kinlon.liu24 分钟前
零信任安全架构--持续验证
java·安全·安全架构·mfa·持续验证
王哲晓1 小时前
Linux通过yum安装Docker
java·linux·docker
java6666688881 小时前
如何在Java中实现高效的对象映射:Dozer与MapStruct的比较与优化
java·开发语言
Violet永存1 小时前
源码分析:LinkedList
java·开发语言
执键行天涯1 小时前
【经验帖】JAVA中同方法,两次调用Mybatis,一次更新,一次查询,同一事务,第一次修改对第二次的可见性如何
java·数据库·mybatis
Jarlen1 小时前
将本地离线Jar包上传到Maven远程私库上,供项目编译使用
java·maven·jar
蓑 羽1 小时前
力扣438 找到字符串中所有字母异位词 Java版本
java·算法·leetcode
Reese_Cool1 小时前
【C语言二级考试】循环结构设计
android·java·c语言·开发语言