目录
一、项目背景
二、项目功能
三、测试计划
1、功能测试
测试用例编写
部分手工测试
上述测试部分出现bug
2、UI自动化测试
1.环境搭建
2.注册测试
3.登录测试
4.退出测试
5.论坛主页面显示测试
6.发布帖子测试
7.删除帖子测试
8.点赞测试
9.修改个人信息测试
3、性能测试
之前有对自己的项目进行过一些测试, 后来想想还是打算写一个比较全部全面的测试博客. 方便后边学习可以进行改进和对比.
网页论坛是一个基于 Springboot 的前后端分离的系统。使用了数据库进行存储数据,并进行部署服务器。实现的功能主要有:用户账号的登录和注册、发布帖子、点赞和回复感兴趣的帖子、个人信息的编辑,以及查看其他用户的发帖信息。
项目链接: 在线论坛 - 用户登录 欢迎大家访问~
核心功能包括: 注册、登录、退出
帖子操作:发布、查看、点赞、编辑帖子、删除、回复
用户操作:查看别人的详细信息、编辑个人信息、查看历史帖子、修改密码
注册:用户输入对应的信息,注册的用户名不存在的时候则注册成功,并跳转至登录页面
登录:用户输入正确的用户名和密码后,会跳转到论坛界面
退出:用户点击退出头像下方的退出按钮会退出登录,并跳转至登录界面
论坛界面:用户可以进行发布帖子,并选择不同的版块进行浏览帖子,查看帖子详情并进行点赞和回复,选择不同的版块可以看到对应版块的帖子总数,还可以看到各个帖子的浏览量以及点赞数
个人中心:用户可以进入个人中心进行查看和修改自己的信息,包括:昵称、邮箱、电话号码,个人简介等,包括修改密码
我的帖子:用户可以在这个界面看到自己发布的所有帖子,还可以在帖子详情页进入到对应的作者或者读者的界面进行浏览他们的历史帖子,此页面还会显示发布的帖子数量,个人简介,邮箱,以及用户注册日期
1.注册
正常注册(test1哪个账号自动化测试的时候已经使用,这里注册新的一个用户名:猫猫 123)
点击注册后成功跳转至登录页面:
错误注册:
这里使用刚才注册过的用户名
输入信息不全的时候页面会自动判定:
输入的密码和确认密码不一致的时候,页面自动检测:
2.登录
正常登录:用户名密码输入正确
预期结果:登陆成功并跳转页面到首页
实际结果:
异常登录:用户名错误
预期结果:登陆失败
实际结果:
异常登录:密码错误
预期结果:登陆失败
实际结果:
3.发布帖子:
正常操作:帖子标题+帖子正文,正常输入
预期结果:发布成功并跳转到首页,可以看到自己的帖子在最上边,并且可以在对应版块类别下看到自己的帖子且对应版块下的帖子数加1,并可以在自己的帖子中心(历史帖子)中看到帖子,且对应的自己发布的帖子数加1
实际结果:
异常操作:帖子标题或者帖子正文为空
预期结果:发布失败
实际结果:
4.回复:
正常操作:留言自己刚才的帖子
预期结果:可以看到自己的留言,留言的帖子下显示的留言数会加一
实际结果:
5.修改个人信息
正常操作:正常修改
预期结果:修改成功并且界面的相应信息显示最新修改的
实际结果:
异常操作:修改的值没有发生变化
预期结果:不应该修改成功
实际结果:
1.个人中心的帖子数量修改不及时,在刚发布的时候那里刷新几次但是显示的帖子数量并没有改变,后边修改个人信息的时候才显示。
2.修改个人信息的时候,如果对应的信息并没有发生变化,应该提示请进行修改。
3.编辑界面编辑器的显示格式错误。
引入依赖
org.seleniumhq.selenium
selenium-java
4.8.3
commons-io
commons-io
2.13.0
org.junit.jupiter
junit-jupiter-api
5.9.2
org.junit.jupiter
junit-jupiter-params
5.9.2
org.junit.platform
junit-platform-suite
1.9.2
org.junit.jupiter
junit-jupiter-engine
5.9.2
用 junit 的注释方便我们操作:
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class InitAndEnd {
public static WebDriver webDriver;
@BeforeAll
public static void Init(){
webDriver=new ChromeDriver();
}
@AfterAll
public static void End(){
webDriver.quit();
}
}
正确输入后,点击注册跳转至登录界面,则认为注册成功
import org.example.forumTest.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 java.time.Duration;
import java.util.concurrent.TimeUnit;
import static java.lang.Thread.sleep;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class forumCases extends InitAndEnd {
//实例化驱动
@BeforeAll
static void init(){
webDriver=AutotestUtils.getWebDriver();
}
/**
* 注册测试
*/
@Disabled
@ParameterizedTest
@CsvSource({"test1,测试用户1,123"})
void register(String username,String nickname,String password) throws InterruptedException {
//进入注册页面
webDriver.get("http://49.235.120.221:58080/sign-up.html");
//输入相应的数据
webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
webDriver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);
webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
webDriver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(password);
//勾选协议
webDriver.findElement(By.cssSelector("#policy")).click();
//点击注册
webDriver.findElement(By.cssSelector("#submit")).click();
sleep(3000);
//校验是否注册成功,检验当前页面的url是否成功跳转至登录页面,成功跳转则认为测试成功,否则认为测试不成功
Assertions.assertEquals("http://49.235.120.221:58080/sign-in.html",webDriver.getCurrentUrl());
System.out.println("注册成功");
}
}
登录后可以成功跳转至首页则认为登录成功
也可以换种方式检验:验证登陆后右上角显示的用户昵称是否和登录用户设置的昵称一样(就是注释的部分代码,因为项目页面前端设计不是很好,设置了等待,但是测试了好几遍,特别容易加载不出来,,,,,,)
/**
* 登录测试
*/
@Order(1)
@ParameterizedTest
@CsvSource({"test1,123,测试用户1"})
void Login(String username,String password,String nickname) throws InterruptedException {
webDriver.get("http://49.235.120.221:58080/sign-in.html");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// webDriver.manage().window().maximize();
//填入用户名和密码
webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
//点击登录
webDriver.findElement(By.cssSelector("#submit")).click();
sleep(5000);
//校验是否成功登录
// String nick_name=webDriver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]/a/div")).getText();
// System.out.println(nick_name);
Assertions.assertEquals("http://49.235.120.221:58080/index.html",webDriver.getCurrentUrl());
}
注意:先登录后退出
推出后跳转至登录界面,则认为退出成功
/**
* 退出登录
* @throws InterruptedException
*/
@Test
void logout() throws InterruptedException {
//进入首页
webDriver.get("http://49.235.120.221:58080/index.html");
//点击头像
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
//点击退出
webDriver.findElement(By.cssSelector("#index_user_logout > span")).click();
sleep(3000);
//检验 跳转到登录界面则认为退出登录成功
Assertions.assertEquals("http://49.235.120.221:58080/sign-in.html",webDriver.getCurrentUrl());
System.out.println("退出成功");
}
首页显示的帖子个数应该不为0,则认为通过
文章标题不是空的,则认为正确显示
注意:后边的测试内容都要先执行登录操作
/**
* 论坛首页测试
*/
@Disabled
@Order(2)
@Test
void post(){
webDriver.get("http://49.235.120.221:58080/index.html#");
//获取首页帖子的个数不为0则认为测试通过
int num=webDriver.findElements(By.cssSelector("div.text-truncate")).size();
webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);
System.out.println(num);
Assertions.assertNotEquals(0,num);
}
/**
* 帖子显示校验
*/
// @Disabled
@Test
void postArticle(){
//打开首页
webDriver.get("http://49.235.120.221:58080/index.html#");
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
//查看帖子,只要标题不为空则认为正确
String text = webDriver.findElement(By.cssSelector("strong")).getText();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
Assertions.assertNotNull(text);
}
@ParameterizedTest
@CsvSource({"标题,正文"})
void creat(String title,String context) throws InterruptedException {
//进入首页
webDriver.get("http://49.235.120.221:58080/index.html");
//点击发布帖子
webDriver.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")).click();
//输入标题,正文
webDriver.findElement(By.cssSelector("#article_post_title")).sendKeys(title);
sleep(2000);
//这里正文不可以使用上边的输入方式,因为编辑器使用的是第三方软件
//执行js(进行输入)
// ((JavascriptExecutor)webDriver).executeScript("document.querySelector(\"#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap.CodeMirror-empty > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div\").value="+context);
webDriver.findElement(By.cssSelector(".CodeMirror-cursors")).sendKeys(context);
sleep(1000);
//点击发布
webDriver.findElement(By.cssSelector("#article_post_submit")).click();
//跳至首页,就认为发布成功
Assertions.assertEquals("首页",webDriver.findElement(By.cssSelector("#article_list_board_title")).getText());
}
项目的前端的确认页用的不是弹窗,所以这里不用弹窗的操作。
//删除帖子
@Test
void delete(){
webDriver.get("http://49.235.120.221:58080/index.html");
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
webDriver.findElement(By.cssSelector("#index_user_profile")).click();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
webDriver.findElement(By.cssSelector("#profile_article_body > li:nth-child(1) > div.card.timeline-event-card > div > div > div > div > div.text-truncate > a > strong")).click();
//点击删除
webDriver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div:nth-child(1) > div.col-9.card.card-lg > div.card-footer.bg-transparent.mt-auto.justify-content-end > div > div:nth-child(3) > div > a")).click();
//处理弹窗 点击确定
webDriver.findElement(By.cssSelector("#details_artile_delete")).click();
// webDriver.switchTo().alert().accept();
//检查
//跳转至首页了
Assertions.assertEquals("首页",webDriver.findElement(By.cssSelector("#article_list_board_title")).getText());
}
//点赞
@Test
void like() throws InterruptedException {
webDriver.get("http://49.235.120.221:58080/index.html");
webDriver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong")).click();
//点赞数
WebElement element=webDriver.findElement(By.cssSelector("#details_article_likeCount"));
//点赞
webDriver.findElement(By.cssSelector("#details_btn_like_count")).click();
//若是点赞后的点赞数量和操作之前的值不一样则认为通过
Assertions.assertNotEquals(element.getText(),element.getText()+1);
}
这里对的代码是调整的,根据本来的名字的长度进行删除,不是不然可能不会过去
//修改个人信息
@Test
void modify(){
//进入个人中心
webDriver.get("http://49.235.120.221:58080/index.html");
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
webDriver.findElement(By.cssSelector("#index_user_settings")).click();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
//这里修改一个昵称和邮箱地址
webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(Keys.BACK_SPACE);
webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(Keys.BACK_SPACE);
webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(Keys.BACK_SPACE);
webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(Keys.BACK_SPACE);
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys("修改昵称");
webDriver.findElement(By.cssSelector("#setting_submit_nickname")).click();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
//继续修改邮箱地址
webDriver.findElement(By.cssSelector("#setting_input_email")).click();
webDriver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(Keys.BACK_SPACE);
webDriver.findElement(By.cssSelector("#setting_input_email")).sendKeys("地址1");
webDriver.findElement(By.cssSelector("#setting_submit_email")).click();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
//检验 返回主页面
String s=webDriver.findElement(By.cssSelector("#index_nav_nickname")).getText();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
System.out.println(s);
Assertions.assertEquals("修改昵称",s);
//在历史中心检验个人简介是否修改成功
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
webDriver.findElement(By.cssSelector("#index_nav_avatar")).click();
webDriver.findElement(By.cssSelector("#index_user_profile")).click();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
String ss=webDriver.findElement(By.cssSelector("#profile_email")).getText();
webDriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
Assertions.assertEquals("地址1",ss);
}
要注意测试的执行顺序,以及对哪个页面进行测试,对测试的结果进行验证的方法的设计。
还有就是要注意文本的清空操作,很多操作需要先清空才能进行正确的输入。
还有一点页面的前端设计不一样的时候,有的页面加载缓慢,就需要注意使用等待。
亮点:
可以对使用场景多的页面进行自动化测试,加快测试工作的效率。
合理使用 junit 的一些注解避免生成过多的对象造成资源浪费,加快了自动化的执行效率。
使用了参数化,提高了代码的简洁度。
测试套件大大加快了执行的效率。