不断学习,不断总结是我们人生很重要的一环,在学习了前面基础的Java语法、数据结构、计算机操作系统、网络,以及SSM框架之后,为了巩固所学的知识,我对比当下知名的博客系统网站,自己也实现了一个简易版本的博客系统,并对系统做了功能、自动化测试。
前言
1、博客系统项目使用的是SSM框架进行前后端分离,前端通过主流Ajax构造请求传给后端,后端接收到请求,解析请求中的参数,连接数据库并完成功能实现,前端接收服务器的响应,将结果渲染到页面上。
2、前端实现了六个页面,依次是登录页面、我的博客列表页、所有博客列表页、注册页面、写博客页面、博客详情页。
3、该博客系统后端实现登录、注册、注销、编写博客、删除博客接口等基本功能,登录功能中采用手写加盐算法解决密码明文展示问题,采用拦截器检验用户进行某些操作是否处于登录状态,用户状态信息session持久化到Redis中,可以进行分布式部署等。
提示:以下针对博客系统进行测试。
在进行测试之前,最重要的一步就是编写测试用例,下面我们就博客系统编写测试用例。
一、功能测试
用于编写的测试点较多,不能一一展示,下面以主要测试点作为功能测试展示的例子。
- 登录成功
- 测试写博客
- 发布成功并查看博客详情
- 删除博客
点击进入我的博客列表页,发现刚才博客记录正常删除了。
- 注销
点击右上角注销按钮,成功注销,并跳转到登录页面。
二、自动化测试
自动化测试的目的就是编写代码自动的帮我们进行人工测试,但是自动化测试并不能完全替代手工测试,下面,我们对于博客系统的主要界面进行自动化测试。
- 在pom.xml中引入相关依赖
<dependencies>
<!-- 引入selenium4自动化测试框架 -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.7.1</version>
</dependency>
<!-- 引入junit5单元测试框架 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.9.2</version>
</dependency>
<!-- junit5框架参数化 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.9.2</version>
</dependency>
</dependencies>
- 输入正确账号和密码,测试通过
public static Stream<Arguments> Param() {
return Stream.of(Arguments.arguments("http://62.234.178.244:8080/myblog_list.html","zhiyaocheng","1234"));
}
@ParameterizedTest
@MethodSource("Param")
public void LoginSuccess(String myblog_list,String username,String password) throws InterruptedException {
// 1.打开博客登录页面
webDriver.get("http://62.234.178.244:8080/login.html");
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 2.输入正确的账号:zhiyaochneg
webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 3.输入正确的密码:1234
webDriver.findElement(By.cssSelector("#password")).sendKeys(password);
// 4.点击提交按钮
webDriver.findElement(By.cssSelector("#submit")).click();
Thread.sleep(3000);
String cur_url = webDriver.getCurrentUrl();
System.out.println(cur_url);
// 5.跳转到列表页
// 获取到当前页面的url,如果当前url=“http://62.234.178.244:8080/myblog_list.html”,测试通过,否则测试不通过
Assertions.assertEquals(myblog_list,cur_url);
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 跳转页面上展示的用户信息是zhiyaocheng,测试通过,则测试不通过
String cur_username = webDriver.findElement(By.cssSelector("h3")).getText();
Assertions.assertEquals(username,cur_username);
}
- 我的博客列表页数量不为0
@Test
public void BlogList() throws InterruptedException {
// 1.打开博客列表页
webDriver.get("http://62.234.178.244:8080/myblog_list.html");
webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);
// 2.获取页面上所有标题对应的元素
int titleSize = webDriver.findElements(By.cssSelector(".title")).size();
System.out.println(titleSize);
Thread.sleep(5000);
// 3.如果元素不为0,测试通过
Assertions.assertNotEquals(0,titleSize);
}
4. 博客详情页校验,当前页面url、博客标题、当前页面title
@Test
public void BlogDetail() {
// 1.找到第一篇博客的查看全文按钮,点击
webDriver.findElement(By.xpath("//*[@id=\"artDiv\"]/div[1]/a[1]")).click();
// 2.获取当前页面url
String cur_url = webDriver.getCurrentUrl();
// 3.获取当前页面的title
String cur_title = webDriver.getTitle();
// 4.获取当前页面的博客标题“这是我的第一篇博客”
String cur_blog_title = webDriver.findElement(By.cssSelector("#title")).getText();
// 4.判断当前url和title,是否测试通过
Assertions.assertEquals("博客正文",cur_title);
Assertions.assertEquals("这是 我的第一篇博客",cur_blog_title);
if (cur_url.contains("http://62.234.178.244:8080/blog_content.html")) {
System.out.println("测试通过");
}else {
System.out.println(cur_url);
System.out.println("测试不通过");
}
}
- 写博客
@Test
void EditBlog() throws InterruptedException {
// 找到写博客按钮,点击
webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 通过Js讲鼻涕进行输入
((JavascriptExecutor)webDriver).executeScript("document.getElementById(\"title\").value=\"自动化测试\"");
sleep(3000);
// 点击发布
webDriver.findElement(By.cssSelector("#submit")).click();
sleep(3000);
// 获取当前页面url
String cur_url = webDriver.getCurrentUrl();
Assertions.assertEquals("http://42.192.83.143:8563/blog_system/blog_list.html", cur_url);
}
6、检验已发布博客标题和发布时间
@Test
void BlogInfoChecked() {
webDriver.get("http://42.192.83.143:8563/blog_system/blog_list.html");
// 获取第一篇博客标题
String first_blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > div.title")).getText();
// 获取第一篇博客发布时间
String first_blog_time = webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/div[2]")).getText();
// 校验博客标题是不是自动化测试
Assertions.assertEquals("自动化测试", first_blog_title);
// 如果时间是2023-5-23年发布的,测试通过
if(first_blog_title.contains("2023-05-23")) {
System.out.println("测试通过");
} else {
System.out.println("当前时间是:" + first_blog_time);
System.out.println("测试不通过");
}
}
- 删除刚才发布的博客
@Test
void DeleteBlog() throws InterruptedException {
// 打开博客列表页面
webDriver.get("http://42.192.83.143:8563/blog_system/blog_list.html");
// 点击全文按钮
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
webDriver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > a")).click();
// 点击删除按钮
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(7)")).click();
sleep(3000);
// 博客列表页第一篇博客标题不是“自动化测试”
String first_blog_title = webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/div[1]")).getText();
// 校验当前博客标题不等于“自动化测试”
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
Assertions.assertNotEquals(first_blog_title, "自动测试");
}
- 注销
@Test
void Logout() {
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();
webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
// 校验url(登录url)
String cur_url = webDriver.getCurrentUrl();
Assertions.assertEquals("http://42.192.83.143:8563/blog_system/blog_login.html", cur_url);
// 校验提交按钮
WebElement webElement = webDriver.findElement(By.cssSelector("#submit"));
Assertions.assertNotNull(webElement);
}
自动化测试优点
(1)使用了junit5框架中提供的注解,避免生成过多的对象,造成时间和资源的浪费,提高了自动化的执行效率。
(2)只创建一次驱动对象,避免每个用例重复创建驱动对象造成时间和资源的浪费。
(3)使用参数化,保持用例的简洁,提高代码的可读性,同时也方便存储大量数据的.csv文件导入。
(4)使用测试套件,降低自动化测试的工作量,因为通过套件就可以一次执行所有运行的测试用例。
(5)使用了隐式等待,提高了自动化的运行效率,提高了自动化的稳定性。