小小论坛系统测试报告

1.项目背景

论坛博客系统采用前后端分离的方法来实现,同时使用了数据库来存储相关的数据,同时将其部署到云服务器上。前端主要有四个页面构成:登录页、列表页、详情页以及编辑页,以上模拟实现了简单的论坛系统。其结合后端将支持用户注册、登录、发帖、回帖、点赞、私信等基本功能。系统将具备良好的安全性。系统将支持高并发处理,确保在用户量剧增时依然能够稳定运行。该论坛系统可以实现个人用户简单的文章记录,时间、标题、内容以及发布者等都可以进行详细地查看。

1.1测试目标

  主页面测试覆盖达到90%

1.2被测系统

forum: 基于spring的论坛系统-前后端分离 (gitee.com)

1.3 测试接口

根据Swagger自动生成的Api说明文档,编写接口测试用例,利用Jmeter完成接口测试

http://127.0.0.1:58080/swagger-ui/index.html#

1.3测试计划

测试类别

测试工具

功能测试

手动

接口测试

Swagger、postman

自动化测试

selenium

性能测试

jmeter

2.测试分类

2.1功能测试

该个人博客系统主要实现了以下几个功能:登录、注销、写博客以及删除博客等功能。

  1. 注册功能:用户进入登录页后如果没有账号可以进行注册,点击注册按钮后进入用户注册页面,完善相关信息后点击注册即可注册账号。
  2. 登录功能:用户在注册完成之后进行账号登录,登录成功后就会跳转到列表页面。在右上角存在发布帖子按钮,但是在未登录情况下按下均只会跳转到登录页面。
  3. 编辑个人信息功能:右上角点击个人头像会弹出个人中心以及退出按钮,点击个人中心即可跳转到个人信息编辑页面。
  4. 列表页面:可以在列表页查看有限数量的帖子简介,其包括作者、标题、发布时间以及内容概要。在上侧可以看到分类的模块。在右上角有主页、写博客和退出三个功能:主页即列表页,写文章即帖子编辑页,退出即退出账号,回到登录页面。
  5. 发布帖子功能:在登录之后的界面点击“发布帖子”之后就会进入编辑页面,此时就可以进行帖子的编写,点击“发布”后就可以成功发布文章,此时就会跳转到列表页。
  6. 删除帖子功能:用户在点击自己的帖子之后会跳转到帖子详情页,右下角有点赞、删除和编辑帖子的按钮,点击之后即可操作。
  7. 修改帖子功能:用户在点击自己的帖子之后会跳转到帖子详情页,右下角有点赞、删除和编辑帖子的按钮,点击之后即可操作。
  8. 发送/读取站内信功能:用户登录后右上角有站内信提示按钮,点击后即可发送和读取站内信。

2.1.1测试用例

2.1.2执行操作步骤/截图

1)正常登录

2)编辑帖子测试

3)发布成功并查看详情页

4)删除帖子

进入详情页并点击“删除”后再次点击“删除”之后成功删除,刚才做发布的“游啊游”已经被成功删除。

5)点赞功能:点击进入帖子详情页后点击“点赞”按钮,点赞数显示加一。

6)发送站内信:点击进入帖子详情页后点击“发私信”按钮即可编辑站内信,点击发送即可成功发出。

    1. 退出:用户登录后右上角有站内信提示按钮,点击后即可发送和读取站内信。

3.测试结果

测试用例100%通过

2.2界面测试

2.2.1测试用例

2.2.2测试结果

 符合预期。

2.3兼容性测试

2.3.1测试用例

2.3.2测试执行

不同浏览器:Microsoft Edge与Google Chrome

不同设备:移动端

2.3.3测试结果

符合预期。

2.4易用性测试

2.4.1测试用例

2.4.1测试结果

符合预期。

2.5自动化测试

  针对论坛系统项目进行测试,主要负责四个模块:登录页、列表页、详情页和编辑页,主要功能包括:登录、编辑并发布帖子、查看详情、删除博客以及退出等功能。对于论坛系统的测试主要就是针对主要功能进行测试,然后按照页面书写测试类。

2.5.1测试用例

以页面书写测试类,然后对主要功能进行测试。

2.5.2 脚本编写

a.根据脑图进行测试用例的编写:每个页面一个测试类,然后再各个测试类中进行测试用例的编写。

b.注意公共属性需要单独放一个类,方便进行代码复用。

c.使用测试套件便于运行以及修改。

d.创建启动以及现场截图就是会频繁进行复用,所以单独创建一个类进行存储。

e.注意添加隐式等待,为了确保页面正确加载显示。

i 添加相关依赖pom.xml

ii 新建包并在包下创建测试类以及公共类

         <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>5.8.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

按照页面分类,每个页面是一个Java文件,页面下所有的用例统一管理。

 

  1. 公共类Utils

创建驱动对象、等待、保存现场截图

ps:在保存现场截图的时候命名是按时间来进行文件夹的划分,然后图片的名称要体现出测试类的类名,方便进行问题的追溯。

注意文件名的动态获取,注意时间格式的设置。

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(2));
        }
        return driver;
    }
    public  Utils(String url){
        //调用driver对象
        driver = createDriver();
        //访问url
        driver.get(url);
    }
    //截图
    public void getScreenShot(String str) throws IOException {
        //文件夹格式
        SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");
        //图片格式
        SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");  //SS:毫秒级别

        String dirTime = sim1.format(System.currentTimeMillis());   //获取当时时间戳
        String fileTime = sim2.format(System.currentTimeMillis());  //文件名为当天日期

        //./src/test/image/2024-07-17/test01-184033.png  预期截图保存路径
        String filename = "./src/test/image/"+dirTime+"/"+ str +"-" + fileTime +".png";
        File srcfile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); //输出为文件形式
        FileUtils.copyFile(srcfile,new File(filename));
    }
}
  1. 登录页面测试LoginPage.java

① 创建驱动,并打开页面
② 测试页面是否正常打开
③ 测试正常登录:多参数测试
④ 测试异常登录:用户名/密码错误的情况
⑤ 注意测试的顺序,可能会因为执行顺序不对导致测试失败
⑥ 注意清空内容后才能再次输入用户名以及密码

public class LoginPage extends Utils {
    public static String url = "http://121.40.27.219:58080/sign-in.html";
    public LoginPage(){
        super(url);
    }
    /*检查页面是否加载成功*/
    public void LoginPageRight() throws IOException, InterruptedException {
        //通过查看页面元素是否存在来检查页面是否加载成功
        driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.text-center.mb-4 > img"));
        //登录输入框
        driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div"));
        getScreenShot(getClass().getName());

    }

    /*检查能否正常登录*/
    //检查登录功能----成功登录
    public void LoginSuc() throws IOException, InterruptedException {
        driver.findElement(By.cssSelector("#username")).sendKeys("duan");
        driver.findElement(By.cssSelector("#password")).sendKeys("123456");
        driver.findElement(By.cssSelector("#submit")).click();
       //检查点击后是否加载成功
        driver.findElement(By.cssSelector("#article_list_board_title"));
        //通过页面标题检查是否登录成功
        String expect = driver.getTitle();
        assert expect.equals("小小论坛");
//        getScreenShot(getClass().getName());
//        driver.navigate().back();
//        driver.findElement(By.cssSelector("#topBannerBox > div > div.right-menu > div > div > i")).click();
//        Alert alert = driver.switchTo().alert();
//        alert.accept();
//        System.out.println("111");
//        driver.findElement(By.xpath("/html/body/ul/li[2]")).click();
//        driver.get(url);
    }
    //检查登录功能----登录失败
    public void LoginFail() throws IOException {
        /*输入错误信息*/
        //返回登录页
        driver.navigate().back();
        //法一:通过clear清空输入框
        driver.findElement(By.cssSelector("#username")).clear();
        driver.findElement(By.cssSelector("#password")).clear();
        //法二:刷新清空输入框
        driver.navigate().refresh();

        driver.findElement(By.cssSelector("#username")).sendKeys("zhangsan");
        driver.findElement(By.cssSelector("#password")).sendKeys("123");
        driver.findElement(By.cssSelector("#submit")).click();
        //通过查找警告框是否存在来检查登录是否失败
        driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div"));

        getScreenShot(getClass().getName());
    }
}

 列表页测试ListPage.java

① 测试帖子列表页是否可以正常打开
② 测试列表页是否可以正常跳转至详情页
③ 测试未登录的直接链接是否会跳转到登录页面,顺便测试了“退出”按钮

public class ListPage extends Utils {
    public static String url = "http://121.40.27.219:58080/index.html";
    public ListPage() {
        super(url);
    }
   /* 未登录状态下---访问列表页*/
    public void ListNoLogin() throws IOException {
        getScreenShot(getClass().getName());
        //1.保证未登录状态
//        driver.navigate().back();
        driver.navigate().refresh();
        driver.findElement(By.cssSelector("body > div > div > div > div:nth-child(1) > div > div.card.card-md > div"));
        //driver.get(url);
        //通过查询列表页的元素来判断是否进入列表页
        driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div > div"));
    }
}

  1. 编辑页测试EditPage.java

① 测试编辑页是否可以正确打开
② 测试帖子是否可以正常发布:元素齐全 or 部分元素
③ 测试“发布帖子”按钮是否可以正常使用
④ 由于编辑列表是第三方插件可能出现无法交互异常报错

Solution:本身存在内容/使用键盘操作

public class EditPage extends Utils {
    public static String url = "http://121.40.27.219:58080/article.html";

    public EditPage() {
        super(url);
    }

    public void EditSuc() throws InterruptedException {
        driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试01");
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));
//        wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("#edit_article_content_area > div.CodeMirror.cm-s-default.CodeMirror-wrap > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre")));
        WebElement ele = driver.findElement(By.cssSelector("#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre"));
        Actions actions = new Actions(driver);
        //perform() 为了在页面看到效果
        actions.doubleClick(ele).perform();
        actions.keyDown(Keys.DELETE).perform();
        actions.moveToElement(ele).sendKeys("测试01").perform();
        Thread.sleep(3000);
        driver.quit();
    }
}

  1. 详情页测试DetailPage.java

① 测试详情页的正确打开:有Id和没有Id两种情况
② 测试“删除”按钮是否可用,注意比较的是时间,因为标题可能会存在为空的情况
③ 执行顺序
④ 一定要注意导航回到列表页的操作

public class DetailPage extends Utils {
    public static String url = "http://121.40.27.219:58080/index.html";
    public DetailPage() {
        super(url);
    }
    public void DetailSuc() throws InterruptedException {
        //点击帖子进入详情页
        driver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong")
        ).click();
        //通过查找详情页的元素来判断是否进入详情页
        driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div:nth-child(1) > div.col-9.card.card-lg"));
    }
}

2.5.3测试结果

自动化测试用例数量

2

自动化测试结果

pass:2/2

问题是否修复

2.6 性能测试

  使用jmeter进行简单性能测试:针对登录、编写并发布帖子以及删除帖子、退出等功能进行简单的性能测试。

然后在实现的过程中,插入集合点以及事务等,并通过设置来实现用户的并发操作。

2.6.1 弱压力场景

模拟5分钟之内 1000 个用户访问服务器资源,这里访问博客列表,要求平均响应时间在300ms内,且错误率为0。

符合要求。

2.6.2高并发场景

模拟 100 个用户同时访问服务器资源,要求平均响应时间在300ms内,且错误率为0。

符合预期。

2.6.3高频率场景

模拟2个用户以20QPS的频率访问服务器资源持续10秒,要求平均响应时间在300ms内,错误率为0。

符合预期。

3.测试总结

3.1 功能测试:验证了用户注册、登录、发帖、回帖、编辑和删除帖子等核心功能的正确性和完整性。测试结果显示,所有功能均按预期工作,无重大缺陷。

3.2 接口测试:通过自动化测试脚本对API进行了测试,确保了数据传输的准确性和安全性。测试覆盖了所有端点,包括用户认证、帖子管理和评论功能。

3.3 界面测试:对前端界面进行了视觉和布局测试,确保在不同设备和分辨率上均能提供一致的用户体验。界面响应式设计在多种屏幕尺寸下表现良好。

3.4 兼容性测试:系统在主流浏览器和操作系统上进行了测试,包括Chrome和Edge,确保了跨平台的兼容性。

3.5 易用性测试:通过用户测试收集了反馈,优化了用户界面和交互流程,提高了系统的用户友好度。测试结果表明,用户能够轻松地导航和使用系统。

3.6 性能测试:模拟了高并发用户访问场景。系统在测试中表现出良好的稳定性和响应速度,满足了性能要求。

综上所述,论坛系统在各项测试中表现稳定,满足了项目的质量标准,为上线做好了准备。
 

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值