1.项目背景

这是一个基于Spring+前后端分离的论坛系统项目

本项目是一款集用户管理、帖子互动、站内通信于一体的论坛类应用,由本人独立完成设计、开发、测试及云服务器部署的全流程工作

1.1 项目简介

模块设计

  • 用户模块:实现用户登录、注册及个人信息维护功能,保障用户身份管理与信息安全。

  • 帖子模块:支持帖子发布、管理、列表展示及点赞互动,满足用户内容创作与互动需求。

  • 帖子回复功能:实现针对帖子的评论与互动回复,强化社区交流属性。

  • 站内信功能:支持向指定用户发送消息,采用长轮询技术实现实时消息推送,提升用户沟通效率。

模拟服务器有效地将消息推送到客户端(或浏览器)

技术栈

  • 后端:基于 Spring Boot + Spring MVC 构建服务端逻辑,以 MySQL 作为数据存储引擎,保障系统稳定性与数据可靠性。

  • 前端:通过 Bootstrap 实现响应式页面布局,结合 jQuery 完成 DOM 操作与 AJAX 异步请求,确保前端交互体验流畅直观。

1.2 应用技术

  • 后端:Spring,Spring Boot,Spring MVC,MyBatis

  • 数据库:MySQL

  • 前端:HTML,CSS,JavaScript,Bootstrap,jQuery3

  • 采用统一返回格式 + 全局错误信息定义,实现前后端交互结果的标准化、一致性处理,提升接口可读性与稳定性

  • 通过 @ControllerAdvice + @ExceptionHandler 注解组合,构建全局异常处理机制,统一拦截、规范化异常响应

  • 利用拦截器技术实现用户登录状态校验,精准拦截未授权请求,强化系统权限管理与操作安全性

  • 借助MybatisGeneratorConfig 工具自动生成常规增删改查方法,大幅提升数据层开发效率,降低重复编码成本

  • 集成Swagger实现自动生成API测试接口

  • 针对数据库高频查询字段建立索引,并通过查询计划工具分析索引生效情况,显著优化数据查询性能与系统响应速度

2.项目模块及实现功能

  1. 注册

  2. 登陆模块

  3. 板块模块

  • 获取首页板块列表

  • 获取某一板块信息

     4.文章模块

  • 发布新贴

  • 获取帖子列表

  • 帖子详情

  • 修改帖子

  • 点赞

  • 删除帖子

  • 获取用户的帖子列表

     5.回复模块

  • 回复帖子

  • 获取回复列表

     6.站内信模块

  • 发送站内信

  • 获取未读消息个数

  • 查询用户的所有站内信

  • 更新为已读

  • 回复站内信

3.测试用例

4.自动化测试

4.1 公共类 Utils

  1. 创建驱动createDriver()

  2. 构造函数(页面初始化)Utils(String url)

  3. 屏幕截图getScreenShot(String str)

  4. 登录封装login()

  5. 滑动页面slidePage(String selector)

package com.example.forum.common;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;

public class Utils {
    public static WebDriver driver;
    public static WebDriver createDriver(){
        if(driver == null){
            WebDriverManager.chromedriver().setup();
            ChromeOptions options = new ChromeOptions();
            //允许访问所有链接
            options.addArguments("--remote-allow-origins=*");
            driver = new ChromeDriver(options);
            //等待
            driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
        }
        return driver;
    }
    public Utils(String url) {
        //调用driver对象
        driver = createDriver();
        //访问url
        driver.get(url);
        //窗口最大化
        driver.manage().window().maximize();
    }

    //屏幕截图
    public void getScreenShot(String str) throws IOException {

        //屏幕截图  时间戳
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sim2 = new SimpleDateFormat("HH-mm-ss");

        String dirTime = sim1.format(System.currentTimeMillis());
        String fileTime = sim2.format(System.currentTimeMillis());

        //根据上面的时间设置 保存图片的文件名字
        String filename = "./src/test/java/com/example/forum/image/" + dirTime + "/" + str +"-" +fileTime + ".png";
        File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
        //复制放到指定位置
        FileUtils.copyFile(srcFile,new File(filename));
    }
    public static void login() throws InterruptedException {
        //输入用户名
        driver.findElement(By.cssSelector("#username")).click();
        driver.findElement(By.cssSelector("#username")).sendKeys("xiaomei");
        //输入密码
        driver.findElement(By.cssSelector("#password")).click();
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        //点击登录按钮
        driver.findElement(By.cssSelector("#submit")).click();

        Thread.sleep(6000);
        //检查点击登录是否成功
        //通过查看logo是否登录成功
        driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > h1 > a > img"));
        //通过查看发布帖子是否登录成功
        driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));
        //返回登录页面
        // driver.navigate().back();
        //刷新页面
        // driver.navigate().refresh();
    }

    //滑动页面
    public static WebElement slidePage(String selector) throws InterruptedException {
        JavascriptExecutor js = (JavascriptExecutor) driver;
        WebElement target = driver.findElement(By.cssSelector(selector));
        js.executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", target);
        //等待页面已经划至发布按钮处
        Thread.sleep(500);

        return target;
    }


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

4.2 注册界面 RegisterPageTest

  1. RegisterPageRight(): 测试注册界面是否正常显示

  2. RegisterFail():测试注册失败(用户已存在,密码和确认密码不一致)

  3. RegisterSuc(): 测试注册成功

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

/**
 * 注册界面测试
 */
public class RegisterPageTest extends Utils {
    public static String url = "我的服务器地址";
    public RegisterPageTest() {
        super(url);
    }

    /**
     * 检查页面是否可以正常打开
     */
    public void RegisterPageRight() throws IOException {
        //论坛logo图标
        driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.mb-4 > img"));
        //检查点击注册按钮
        //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"));
        getScreenShot(getClass().getName());
        System.out.println("页面正常打开");
    }

    //注册失败01--该用户已存在
    public void RegisterFai01() throws IOException, InterruptedException {
        //在登录页面点击注册按钮
        driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.text-muted.mt-3 > a")).click();
        //输入用户名
        driver.findElement(By.cssSelector("#username")).sendKeys("testUser1");
        //输入昵称
        driver.findElement(By.cssSelector("#nickname")).sendKeys("testUser1");
        //输入密码
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        //输入确认密码
        driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123456");
        //点击同意使用条款和隐私服务
        driver.findElement(By.cssSelector("#policy")).click();
        //点击注册
        driver.findElement(By.cssSelector("#submit")).click();
        //获取异常文本
        String fail01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();
        Thread.sleep(500);
        //截图
        getScreenShot(getClass().getName());
        System.out.println(fail01);
        assert fail01.equals("警告");

    }
    //密码和确认密码不一致
    public void RegisterFail02 () throws IOException, InterruptedException {
        //刷新一下页面
        driver.navigate().refresh();
        //输入用户名
        driver.findElement(By.cssSelector("#username")).sendKeys("passwordNotSame");
        //输入昵称
        driver.findElement(By.cssSelector("#nickname")).sendKeys("passwordNotSame");
        //密码
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        //确认密码
        driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123666");
        //点击同意隐私
        driver.findElement(By.cssSelector("#policy")).click();
        //点击注册
        driver.findElement(By.cssSelector("#submit")).click();
        //获取当前异常文本
        String fail02 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(5) > div > div")).getText();
        Thread.sleep(500);
        //屏幕截图
        getScreenShot(getClass().getName());
        //断言
        assert fail02.equals("请检查确认密码");
    }
    /**
     * 注册成功
     */
    public void RegisterSuc() throws IOException, InterruptedException {

        //刷新页面, 清空输入框
        driver.navigate().refresh();

        driver.findElement(By.cssSelector("#username")).sendKeys("testName1");
        driver.findElement(By.cssSelector("#nickname")).sendKeys("testNickname1");
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123456");
        driver.findElement(By.cssSelector("#policy")).click();

        driver.findElement(By.cssSelector("#submit")).click();

        Thread.sleep(3000);

        //点击注册后进入登录界面

        //截图
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5)); //显示等待
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div > h2")));

        getScreenShot(getClass().getName());
        //获取当前页面url
        String ele = driver.getCurrentUrl();
        //如果已经跳转至登录界面, 则注册成功
        assert ele.equals("我的服务器地址");

    }
}

执行自动化测试代码过程中执行的截图如下:

4.3 登陆界面 LoginPage

  1. loginPageRight():测试页面是否正常显示

  2. loginSuc():测试登录功能---成功登录

  3. loginFail():测试登录功能---登录失败,以用户名存在,密码错误和用户名不存在,密码非空作为测试用例

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;

import java.io.IOException;

public class LoginPageTest extends Utils {

    private static final String url = "我的服务器地址";

    public LoginPageTest() {
        super(url);
    }

    /**
     * 检查页面是否可以正常打开
     */
    public void LoginPageRight() {
        //论坛logo图标
        driver.findElement(By.cssSelector("body > div.page.page-center > div > div > div:nth-child(1) > div > div.text-center.mb-4 > img"));
        //检查点击登录按钮
        driver.findElement(By.cssSelector("#submit"));
        System.out.println("页面正常打开");
    }

    //检查登录功能   成功登录
    public void LoginSuc() throws InterruptedException, IOException {
        Thread.sleep(1000);
        //输入用户名
        driver.findElement(By.cssSelector("#username")).click();
        driver.findElement(By.cssSelector("#username")).sendKeys("xiaoshuai");
        //输入密码
        driver.findElement(By.cssSelector("#password")).click();
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        //点击登录按钮
        driver.findElement(By.cssSelector("#submit")).click();
        //检查点击登录是否成功
        //通过查看logo是否登录成功
//        driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > h1 > a > img"));
        //通过查看发布帖子是否登录成功
//        driver.findElement(By.cssSelector("#\\34 04Lounge-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        Thread.sleep(5000);
        //返回登录页面
        driver.navigate().back();
        //刷新页面
        driver.navigate().refresh();
    }

    //检查登录失败01--密码错误
    public void loginFail01() throws IOException, InterruptedException {
        Thread.sleep(1000);
        //输入用户名
        driver.findElement(By.cssSelector("#username")).sendKeys("mypsss");
        //输入密码
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        //点击登录按钮
        driver.findElement(By.cssSelector("#submit")).click();

        Thread.sleep(4000);
        //获取当前异常文本
        String fail01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();
        //截图body > div.jq-toast-wrap.bottom-right > div
        Thread.sleep(500);
        getScreenShot(getClass().getName());
        assert fail01.equals("警告");

    }

    //用户名为空
    public void loginFail02() throws IOException, InterruptedException {
        Thread.sleep(1000);
        //刷新一下
        driver.navigate().refresh();
        //用户名
        driver.findElement(By.cssSelector("#username"));
        //输入密码
        driver.findElement(By.cssSelector("#password")).sendKeys("111111");
        //点击登录按钮
        driver.findElement(By.cssSelector("#submit")).click();

        Thread.sleep(1000);
        //获取异常文本
        String fail02 = driver.findElement(By.cssSelector("#signInForm > div.mb-3 > div")).getText();
        //截图
        getScreenShot(getClass().getName());
        assert fail02.equals("用户名不能为空");
    }

    //密码为空
    public void loginFail03() throws IOException, InterruptedException {
        Thread.sleep(1000);
        //刷新
        driver.navigate().refresh();
        //输入用户名
        driver.findElement(By.cssSelector("#username")).sendKeys("myp");
        //密码
        driver.findElement(By.cssSelector("#password"));
        //点击登录按钮
        driver.findElement(By.cssSelector("#submit")).click();

        Thread.sleep(1000);
        //获取当前异常文本
        String fail03 = driver.findElement(By.cssSelector("#signInForm > div.mb-2 > div > div")).getText();
        //截图
        getScreenShot(getClass().getName());
        assert fail03.equals("密码不能为空");

        quit();
    }
}

执行自动化测试代码过程中执行的截图如下:

4.4 论坛首页 HomePage

  1. HomePageFail():测试未登录状态下进入论坛首页

  2. HomePageSuc():测试登录后正常进入论坛首页

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

/**
 * 论坛首页测试
 */
public class HomePageTest extends Utils {
    private static final String url = "我的服务器地址";
    private static final String LOGIN_URL = "我的服务器登录地址";

    public HomePageTest() {
        super(url);
    }

    /**
     * 未登录状态下, 进入论坛首页
     */
    public void HomePageFail() throws IOException, InterruptedException {
        // 直接访问首页
        driver.get(url);
        System.out.println(url);
        // 等待页面跳转完成(处理延迟,避免获取到跳转前的URL)
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(5));
        wait.until(ExpectedConditions.urlContains("sign-in.html"));

        // 获取当前URL
        String curUrl = driver.getCurrentUrl();
        System.out.println(curUrl);

        // 正确断言:当前URL应等于登录页URL,验证跳转成功
        assert curUrl.equals(LOGIN_URL) : "未登录访问首页未正确跳转至登录页,当前URL:" + curUrl;
        System.out.println("未登录访问首页成功跳转至登录页,测试通过");
    }

    /**
     * 登录后, 可以正常进入论坛首页
     */
    public void HomePageSuc() throws IOException, InterruptedException {
        //登陆操作
        Utils.login();

        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#article_list_board_title")));

        //检查第二个板块是否存在
        driver.findElement(By.cssSelector("#topBoardList > li:nth-child(2) > a > span.nav-link-title"));
        //检查发布帖子按钮
        driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));
        //查看首页
        driver.findElement(By.cssSelector("#article_list_board_title"));

        //截图
        getScreenShot(getClass().getName());

    }

}

执行自动化测试代码过程中执行的截图如下:

4.5 发帖界面 PublishPage

  1. publishPostPage():测试正常进入发帖界面

  2. publishPostSuc():测试正常发布帖子功能

  3. publishPostFail():测试发帖失败

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

/**
 * 发帖界面的相关测试方法
 */
public class PublishPageTest extends Utils {
    public static String url = "我的服务器地址";
    public PublishPageTest() {
        super(url);
    }

    /**
     * 测试正常进入发布帖子界面
     */
    public void publishPostPage() throws InterruptedException, IOException {
        //登录到论坛首页
        Utils.login();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3));
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#nav_board_index > a > span.nav-link-title")));
        //在首页中查找“首页”这个标签页
        driver.findElement(By.cssSelector("#nav_board_index > a > span.nav-link-title")).click();
        Thread.sleep(1000);

        //等待元素加载
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post")));
        //进入页面后查找“发布帖子”
        WebElement element = driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));
        //发布按钮
//        driver.findElement(By.cssSelector("#article_post_submit"));
        getScreenShot(getClass().getName());
        element.click();

    }

    /**
     * 测试正常发布帖子功能
     */
    public void publishPostSuc() throws InterruptedException, IOException {
        //点击板块下拉选择板块
        driver.findElement(By.cssSelector("#article_post_borad"));
        //点击招聘信息
        driver.findElement(By.cssSelector("#article_post_borad > option:nth-child(1)")).click();
        //点击标题, 输入内容
        driver.findElement(By.cssSelector("#article_post_title")).click();
        driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试标题001");
        Thread.sleep(2000);
        //点击内容框,输入内容
        //模拟输入内容
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
        //等待内容输入框加载完成
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(12) > a > i")));


        WebElement element = driver.findElement(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(12) > a > i"));
        element.click();

        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        element.click();


        //将页面划至 发布 按钮处
        JavascriptExecutor js = (JavascriptExecutor) driver;
        WebElement publishButton = driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]"));
        js.executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", publishButton);
        //等待页面已经划至发布按钮处
        Thread.sleep(1000);
        publishButton.click();

    }

    /**
     * 测试发布帖子失败
     */
    public void publishPostFail() throws InterruptedException, IOException {
        //找到发布帖子的按钮
        WebElement element = driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div.col-auto.ms-auto.d-print-none > div > a.btn.btn-primary.d-none.d-sm-inline-block.article_post"));
        element.click();
        //以内容为空作为测试用例
        driver.findElement(By.cssSelector("#article_post_title")).sendKeys("标题");

        //将页面划至 发布 按钮处
        JavascriptExecutor js = (JavascriptExecutor) driver;
        WebElement publishButton = driver.findElement(By.xpath("//*[@id=\"article_post_submit\"]"));
        js.executeScript("arguments[0].scrollIntoView({behavior: 'smooth', block: 'center'});", publishButton);
        //等待页面已经划至发布按钮处
        Thread.sleep(1000);
        publishButton.click();

        //当前还在发帖界面则发帖失败
        driver.findElement(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2"));
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }
}

执行自动化测试代码过程中执行的截图如下:

4.6 帖子详情 DetailsPage

  1. DetailsPageRight():测试帖子详情页正常显示

  2. thumbsUp():测试成功点赞

  3. replyPost():测试成功回复帖子

  4. editPageRight():测试编辑帖子页面是否能够正常显示

  5. editSuc():测试成功编辑并发布帖子

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

/**
 * 测试帖子详情页的相关功能
 */
public class DetailsPageTest extends Utils {


    public static String url = "我的服务器地址";

    public DetailsPageTest() {
        super(url);
    }
    /**
     * 测试帖子详情页正常显示
     */
    public void DetailsPageRight() throws InterruptedException {
        Utils.login();
        //将页面滑动至目标元素处  日常生活板块
        WebElement targetPost = Utils.slidePage("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong");
        targetPost.click();
        //检查详情页面是否有元素  向上滑动
        Utils.slidePage("#details_article_title");
        Thread.sleep(1000);

    }

    /**
     * 测试点赞
     */
    public void thumbsUp() throws IOException {

        driver.findElement(By.cssSelector("#details_btn_like_count")).click();
        getScreenShot(getClass().getName());
    }

    /**
     * 测试回复帖子
     */
    public void replyPost() throws InterruptedException, IOException {
        WebElement target = Utils.slidePage("#article_details_reply > div.editormd-toolbar > div > ul > li:nth-child(12) > a");
        target.click();
        //页面滑动至回复按钮
        target = Utils.slidePage("#details_btn_article_reply");
        //点击回复
        target.click();
        getScreenShot(getClass().getName());
    }
    /**
     * 测试编辑帖子页面是否能够正常显示
     */

    public void editPageRight() throws InterruptedException, IOException {

        //检查详情页面是否有元素  向上滑动
        Utils.slidePage("#details_article_title");
        Thread.sleep(1000);

        driver.findElement(By.cssSelector("#nav_board_index > a > span.nav-link-title")).click();
        //将页面滑动至目标元素处  日常生活板块
        WebElement targetPost = Utils.slidePage("#artical-items-body > div:nth-child(2) > div > div.col > div.text-truncate > a > strong");
        targetPost.click();



        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
        //将页面滑动至编辑按钮处
        WebElement target = Utils.slidePage("#details_artile_edit");

        getScreenShot(getClass().getName());
        //点击编辑进入博客编辑页
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#details_artile_edit")));
        driver.findElement(By.cssSelector("#details_artile_edit")).click();
        getScreenShot(getClass().getName());
    }

    /**
     * 测试成功编辑并发布帖子
     */
    public void editSuc() throws InterruptedException, IOException {
        WebElement title = driver.findElement(By.cssSelector("#edit_article_title"));
        title.clear();
        //修改标题
        title.sendKeys("666");

        //将页面滑动至提交按钮处
        WebElement target = Utils.slidePage("#edit_article_submit");
        target.click();

        getScreenShot(getClass().getName());
        //点击提交后回到论坛首页
        driver.findElement(By.cssSelector("#article_list_board_title"));

    }
}

执行自动化测试代码过程中执行的截图如下:

4.7 站内信 MessagePage

  1. postMessageRight():测试发送站内信界面是否正常显示

  2. postMessageSuc():测试成功发送站内信

  3. messageListRight():测试站内信列表界面正常显示

  4. replyMessage():测试成功回复站内信

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

/**
 * 测试站内信相关功能
 */
public class MessagePageTest extends Utils {
    public static String url = "我的服务器地址";
    public MessagePageTest() {
        super(url);
    }

    /**
     * 测试发私信界面是否正常显示
     */
    public void postMessageRight() throws InterruptedException {
        //先登录进入论坛首页
        Utils.login();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#article_list_board_title")));

        //点击CPP
        WebElement target = Utils.slidePage("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong");
        //点击进入到帖子详情页
        target.click();

        Utils.slidePage("#btn_details_send_message");
        //点击作者下面的发私信按钮, 出现发送站内信界面
        driver.findElement(By.cssSelector("#btn_details_send_message")).click();

        driver.findElement(By.cssSelector("#index_message_modal > div > div > div.modal-header > h5"));
        driver.findElement(By.cssSelector("#btn_index_send_message"));
    }

    /**
     * 测试成功发送私信
     */
    public void postMessageSuc() throws IOException, InterruptedException {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待

        //在发送私信窗口的输入框输入内容
        driver.findElement(By.cssSelector("#index_message_receive_content")).sendKeys("你好,小帅");
        //点击发送按钮
        Thread.sleep(1000);
        driver.findElement(By.cssSelector("#btn_index_send_message")).click();

        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * 测试站内信列表界面正常显示
     */
    public void messageListRight() throws InterruptedException, IOException {

        WebElement target = Utils.slidePage("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a");
        //点击右上角的铃铛
        driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > div > a")).click();
        //出现站内信列表
        driver.findElement(By.cssSelector("#offcanvasEndLabel"));

        Thread.sleep(1000);
        getScreenShot(getClass().getName());
    }

    /**
     * 测试回复站内信
     */

    public void replyMessage() throws InterruptedException, IOException {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待

        //找到某一条站内信, 点击
        driver.findElement(By.cssSelector("#index_div_message_list > div > div > div.col.text-truncate > a")).click();
        //点击回复按钮
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#btn_index_message_reply")));
        WebElement replyButton = driver.findElement(By.cssSelector("#btn_index_message_reply"));
        replyButton.click();
        //向输入框输入内容
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_reply_receive_content")));
        driver.findElement(By.cssSelector("#index_message_reply_receive_content")).sendKeys("回复内容");
        //点击发送
        driver.findElement(By.cssSelector("#btn_index_send_message_reply")).click();
        getScreenShot(getClass().getName());

    }
}

执行自动化测试代码过程中执行的截图如下:

4.8 我的帖子 MyPostPage

  1. MyPostPageRight():测试我的帖子界面是否正常显示

  2. DetailPageRight():测试帖子详情是否可以正常访问,详情页是否正常显示

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

/**
 * 测试我的帖子界面是否正常显示
 */
public class MyPostPageTest extends Utils {
    public static String url = "我的服务器地址";

    public MyPostPageTest() {
        super(url);
    }

    /**
     * 测试我的帖子界面是否正常显示
     */
    public void MyPostPageRight() throws IOException, InterruptedException {
        Utils.login();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待

        //点击右上角头像
        WebElement element = driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.dropdown > a"));
        element.click();
        //点击我的帖子
        wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_user_profile")));
        driver.findElement(By.cssSelector("#index_user_profile")).click();

        //进入我的帖子界面
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#index_user_profile")));
        getScreenShot(getClass().getName());
    }

    /**
     * 测试帖子详情是否可以正常访问,详情页是否正常显示
     */
    public void DetailPageRight() throws InterruptedException, IOException {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待

        //点击进入帖子详情页
        Thread.sleep(2000);
        driver.findElement(By.cssSelector("#profile_article_body > li:nth-child(1) > div.card.timeline-event-card > div > div > div > div > div.text-truncate > a")).click();
        //测试页面元素
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#details_article_title")));
        driver.findElement(By.cssSelector("#details_article_title"));
        driver.findElement(By.cssSelector("#details_btn_like_count"));
        getScreenShot(getClass().getName());
    }

}

执行自动化测试代码过程中执行的截图如下:

4.9 个人中心 PersonalCenterPage

  1. PersonalCenterPageRight():个人中心界面是否正常显示

  2. modifyInfoSuc():测试修改个人信息

  3. modifyPasswordSuc():测试修改密码

package com.example.forum.cases;

import com.example.forum.common.Utils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.IOException;
import java.time.Duration;

/**
 * 测试个人中心界面相关功能
 */
public class PersonalCenterPageTest extends Utils {
    public static String url = "我的服务器地址";
    public PersonalCenterPageTest() {
        super(url);
    }

    public void PersonalCenterPageRight() throws InterruptedException, IOException {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待
        //先登录进入论坛首页
        Utils.login();
        //点击右上角头像
        driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.dropdown > a")).click();
        //点击个人中心
        driver.findElement(By.cssSelector("#index_user_settings")).click();

        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        //检查页面是否正常加载
        wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#bit-forum-content > div.page-header.d-print-none > div > div > div > h2")));
        driver.findElement(By.cssSelector("#setting_submit_nickname"));
        driver.findElement(By.cssSelector("#settings_nickname"));
    }

    public void modifyInfoSuc() throws InterruptedException, IOException {

        //对于昵称,邮箱地址,电话,个人介绍, 任意一项都可以直接修改, 这里以昵称作为测试用例
        driver.findElement(By.cssSelector("#setting_input_nickname")).clear();

        //修改昵称
        String oldNickname = driver.findElement(By.cssSelector("#settings_nickname")).getText();
        //输入新昵称
        driver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(oldNickname + "1");
        Thread.sleep(1000);
        getScreenShot(getClass().getName());
        //点击修改
        driver.findElement(By.cssSelector("#setting_submit_nickname")).click();
        getScreenShot(getClass().getName());


        //修改邮箱地址
        WebElement email = Utils.slidePage("#setting_input_email");
        email.clear();
        email.sendKeys("6666@qq.com");

        Thread.sleep(1000);
        getScreenShot(getClass().getName());

        driver.findElement(By.cssSelector("#setting_submit_email")).click();
        getScreenShot(getClass().getName());

        //修改电话号码
        WebElement phone = Utils.slidePage("#setting_input_email");
        phone.clear();
        phone.sendKeys("114514666");

        Thread.sleep(1000);
        getScreenShot(getClass().getName());

        driver.findElement(By.cssSelector("#setting_submit_phoneNum")).click();
        getScreenShot(getClass().getName());

        //修改个人简介
        WebElement info = Utils.slidePage("#settings_textarea_remark");
        info.clear();
        info.sendKeys("这是自动化测试修改个人简历");

        Thread.sleep(1000);
        getScreenShot(getClass().getName());

        driver.findElement(By.cssSelector("#settings_submit_remark")).click();
        getScreenShot(getClass().getName());
    }

    /**
     * 测试修改密码
     */

    public void modifyPasswordSuc() throws InterruptedException, IOException {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(3)); //显示等待


        WebElement target = Utils.slidePage("#settings_submit_password");
        driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("123456");
        //模拟修改密码
        driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123456");
        driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123456");

        //点击提交修改
        driver.findElement(By.cssSelector("#settings_submit_password")).click();
        //跳转至登录界面
        getScreenShot(getClass().getName());
    }
}

执行自动化测试代码过程中执行的截图如下:

5.测试总结

测试用例设计与执行

基于论坛系统注册、登录、首页、发帖、帖子详情、站内信、我的帖子、个人中心8 大核心模块,预计共设计 100 条功能测试用例,现基于自动化测试完成了三十多条测试用例

自动化测试

针对公共类 Utils 及 8 大界面(注册、登录、论坛首页、发帖、帖子详情、站内信、我的帖子、个人中心)

  • 公共类 Utils:设计 5 条用例,全部通过,保障工具类方法的通用性和稳定性。

  • 注册 / 登录界面:共设计 8 条用例,分别通过 8 条,重点验证账号注册、密码校验、登录态保持等核心流程;

  • 论坛首页 / 发帖 / 帖子详情:共设计 10 条用例,分别通过 10条,覆盖帖子列表渲染、发帖格式校验、评论交互等场景;

  • 站内信 / 我的帖子 / 个人中心:共设计 9 条用例,全部通过,验证消息收发、帖子管理、个人信息修改等功能;

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐