在线音乐播放器 —— 测试报告
自动化脚本源代码:Java: 利用Java解题与实现部分功能及小项目的代码集合 - Gitee.com
目录
·前言
一、项目简介
1.项目背景
2.应用技术
(1)后端开发
(2)前端开发
(3)数据库
二、项目功能
三、功能测试
1.编写测试用例
2.测试具体过程
(1)正常登录
(2)异常登录
(3)删除单个音乐
(4)删除选中音乐
(5)喜欢音乐
(6)上传音乐
(7)查询音乐
(8)取消喜欢音乐
四、自动化测试
1.编写自动化测试用例
2.自动化测试代码编写
(1)创建空项目
(2)创建测试用例工具类
(3)创建登录测试用例类
(4)创建音乐列表测试用例类
(5)创建喜欢列表测试用例类
(6)创建上传音乐测试用例类
(7)创建运行测试用例类
3.自动化测试执行结果
五、性能测试
1.创建梯度压测线程组
2.创建 HTTP 请求默认值
3.创建 HTTP Cookie 管理器
4.创建音乐播放器登录请求
5.创建获取音乐列表页请求
6.创建获取喜欢音乐列表页请求
7.性能测试执行结果
8.生成性能测试报告
·总结
·前言
前面文章中,我们把在线音乐播放器项目从零到一的都编写完成完成,并在每个模块编写的过程中,利用 Postman 进行了接口的简单测试,在本篇文章,我将对我们所编写的这个项目进行一个详细的测试并且再对本项目做一个整体的介绍,来检查我们项目中是否还存在问题,这里我们要进行的测试分为:功能测试、自动化测试、性能测试三种,最后将这些测试的过程及结果总结到一起形成这篇测试报告。
一、项目简介
1.项目背景
在数字化时代,音乐作为人们生活中不可或缺的一部分,其消费与传播方式发生了巨大变革。传统的音乐播放模式逐渐向线上转移,人们渴望能够通过便捷的网络平台随时随地畅享丰富多样的音乐资源。本在线音乐播放器项目正是为满足这一市场需求而开发,旨在为用户打造一个功能全面、操作便捷的音乐播放与管理平台,使用户无需受限于本地音乐存储,即可轻松探索、播放和管理海量音乐曲目。
2.应用技术
(1)后端开发
后端开发应用的技术如下所示:
- Spring 框架:作为核心框架,提供了依赖注入等功能,有效管理项目中的组件对象,解耦各模块之间的依赖关系,提高代码的可维护性与扩展性。
- SpringBoot:基于 Spring 进一步简化了项目的初始搭建与配置过程,通过自动配置特性,使开发者能够快速聚焦于业务逻辑开发,大大提高开发效率,同时也便于项目的部署与运维。
- Mybatis:负责数据库访问层的操作,能够将 SQL 查询语句与 Java 代码进行灵活映射,方便对 Mysql 数据库进行数据的持久化操作,如音乐信息、用户数据等的存储与读取,高效处理数据访问需求。
- SpringMVC:遵循 MVC 设计模式,实现了前端请求与后端处理逻辑的清晰分离与高效交互,负责接收并处理来自前端的各种 HTTP 请求,如用户登录、音乐查询与操作等请求,并将处理结果返回给前端页面进行展示。
- BCrypt 加密算法:用于对用户密码进行加密存储,保障用户密码在数据库中的安全性,有效防止密码泄露导致的用户账号安全问题,确保用户信息安全。
(2)前端开发
前端开发应用的技术如下所示:
- HTML:构建页面的基础结构,负责定义页面的各个元素与布局,如音乐列表界面、用户登录界面、喜欢音乐列表展示等页面的骨架搭建。
- CSS:用于美化页面样式,通过设置字体、颜色、背景、布局等样式属性,使页面呈现出美观、舒适的视觉效果,提升用户操作体验与界面友好度。
- JS:为页面添加动态交互功能,如实现音乐播放控制、用户操作响应(如点击登录按钮、添加喜欢音乐等)、数据验证等功能,增强页面的交互性与响应性。
- jQuery:简化了 JavaScript 的开发过程,提供了丰富的插件与便捷的操作方法,方便对页面元素进行选择、事件绑定、动画效果实现等操作,进一步提高前端开发效率与代码简洁性。
- Ajax:用于实现前端与后端的异步数据交互,在不刷新整个页面的情况下,能够在后台与服务器进行数据传输,如实时查询音乐、无刷新更新音乐播放列表等功能,提升用户体验的流畅性与实时性。
(3)数据库
采用 Mysql 关系型数据库进行数据存储,能够高效地组织与管理平台所需的各类数据,包括音乐信息(歌曲名、歌手、音频文件路径)、用户信息(用户名、密码)、用户音乐信息(喜欢音乐),确保数据的完整性、一致性与持久性,为平台的稳定运行提供数据支持。
二、项目功能
本在线音乐播放器项目的核心功能有:登录、上传音乐、删除指定音乐、批量删除选中的音乐、查询要找的音乐、添加音乐至喜欢列表、移除喜欢的音乐。
部分功能的详细介绍如下所示:
- 登录功能:用户名与加密后的密码都已经写入到后端的数据库中了,本项目目前还没有实现注册功能,即:用户名与密码是已经存在的,登录成功后就会跳转到音乐列表页。
- 音乐列表页:在这个页面中,我们可以看到所有的音乐信息,其包括音乐名称,歌手。在每个音乐对应的行中有播放音乐、删除音乐、喜欢音乐的三个按钮,这三个按钮也对应着三个功能,每个音乐前面设计了一个选择框,通过这个可以实现批量删除的操作。
- 喜欢音乐列表页:这个页面的整体布局与音乐列表页布局大致相同,只不过没有喜欢音乐及批量删除选中音乐的功能了,添加了取消喜欢音乐的功能和回到首页的功能,在这个页面中也可以针对喜欢的音乐进行查询操作。
- 上传音乐页面:在这个页面进行的就是上传音乐的操作,并且还有返回首页的连接。
三、功能测试
1.编写测试用例
功能测试的测试用例如下图所示:
2.测试具体过程
(1)正常登录
(2)异常登录
(3)删除单个音乐
(4)删除选中音乐
(5)喜欢音乐
(6)上传音乐
(7)查询音乐
(8)取消喜欢音乐
四、自动化测试
1.编写自动化测试用例
自动化测试的测试用例如下图所示:
2.自动化测试代码编写
(1)创建空项目
① 添加依赖(pom.xml 文件)代码如下所示:
<dependencies><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></dependencies>
② 创建项目结构,如下图所示:
(2)创建测试用例工具类
创建 Utils 类,用它存放我们自动化代码中通用的方法,在这个类中我们要创建的方法如下:
- 创建驱动对象;
- 创建屏幕截图方法;
- 创建构造方法。
有关 Utils 类的具体代码及详细介绍如下所示:
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 void getScreenShot(String str) throws IOException {// 规定时间格式为 年-月-日, 如: 2024-11-17SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");// 规定时间格式为 时分秒毫秒, 如: 171953345SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");// 创建文件夹的名称, 以现在的日期来命名, 用 sim1 来转化时间格式String dirTime = sim1.format(System.currentTimeMillis());// 创建文件名称, 以现在的时间来命名, 用 sim2 来转化时间格式String fileTime = sim2.format(System.currentTimeMillis());// 拼接好完整文件名(包含:存放具体位置,及文件名称)String filename = "./src/test/image/" + dirTime + "/" + str + "-" + fileTime + ".png";// 屏幕截图File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);// 把截图 srcFile 放到指定的位置FileUtils.copyFile(srcFile, new File(filename));}// 创建构造方法, 接收访问页面的 URLpublic Utils(String url) {// 1. 调用 driver 对象driver = createDriver();// 2. 访问 URLdriver.get(url);}
}
(3)创建登录测试用例类
创建 LoginPage 类,在这里编写登录页面的所有测试用例,在这里我们要完成的事情如下:
- 检查登录页面是否正确加载;
- 检查正常登录功能是否正常;
- 检查异常登录功能是否正常。
有关 LoginPage 类的具体代码及详细介绍如下所示:
public class LoginPage extends Utils {// 指定页面的 URLprivate static String url = "http://127.0.0.1:8080/login.html";// 设置显式等待private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));// 创建构造方法, 传入 urlpublic LoginPage() {super(url);}// 测试页面是否成功加载public void loginPageRight() throws InterruptedException {// 通过查看页面元素是否存在来检查页面加载是否成功// 查找状态提示框driver.findElement(By.cssSelector("#message"));// 获取页面标题String title = driver.getTitle();// 验证当前页面标题信息assert title.equals("音乐播放器登录页面");}// 检查登录功能----登录失败public void loginFail() throws InterruptedException {// 1. 测试用户名为空// 刷新当前页面,防止输入框中残留信息driver.navigate().refresh();driver.findElement(By.cssSelector("#user")).sendKeys("123");driver.findElement(By.cssSelector("#submit")).click();// 显式等待弹窗出现wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();// 验证弹窗的文本信息assert alert.getText().equals("用户名或密码错误!");// 点击确定,关闭弹窗alert.accept();// 2. 测试用户名不存在driver.findElement(By.cssSelector("#user")).sendKeys("usseee");driver.findElement(By.cssSelector("#password")).sendKeys("123");driver.findElement(By.cssSelector("#submit")).click();wait.until(ExpectedConditions.alertIsPresent());assert alert.getText().equals("用户名或密码错误!");alert.accept();// 3. 测试用户名正确, 密码为空driver.findElement(By.cssSelector("#user")).sendKeys("lisi");driver.findElement(By.cssSelector("#submit")).click();wait.until(ExpectedConditions.alertIsPresent());assert alert.getText().equals("密码错误! ");alert.accept();// 4. 测试用户名正确, 密码错误driver.findElement(By.cssSelector("#user")).sendKeys("lisi");driver.findElement(By.cssSelector("#password")).sendKeys("232424");driver.findElement(By.cssSelector("#submit")).click();wait.until(ExpectedConditions.alertIsPresent());assert alert.getText().equals("密码错误! ");alert.accept();}// 检查登录功能----登录成功public void loginSuc() throws InterruptedException {// 刷新当前页面,防止输入框有残留信息driver.navigate().refresh();// 输入存在的用户名和正确的密码driver.findElement(By.cssSelector("#user")).sendKeys("lisi");driver.findElement(By.cssSelector("#password")).sendKeys("123456");driver.findElement(By.cssSelector("#submit")).click();// 显式等待, 等待弹窗出现wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();// 验证弹窗文本信息assert alert.getText().equals("登录成功! ");// 点击确定,关闭弹窗alert.accept();// 获取当前页面标题String title = driver.getTitle();// 验证当前页面标题信息,观察是否成功跳转assert title.equals("在线音乐列表");}}
(4)创建音乐列表测试用例类
创建 ListPage 类,在这里编写列表页面的所有测试用例,在这里我们要完成的事情如下:
- 检查列表页面是否能正确加载;
- 检查音乐的查询功能是否正常;
- 检查音乐的删除功能是否正常;
- 检查选中音乐的删除功能是否正常;
- 检查喜欢音乐的功能是否正常。
有关 ListPage 类的具体代码及详细介绍如下所示:
public class ListPage extends Utils {// 指定页面的 URLprivate static String url = "http://127.0.0.1:8080/list.html";// 设置显式等待private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));public ListPage() {super(url);}// 测试页面是否正确加载public void listPageRight() {driver.findElement(By.cssSelector("#exampleInputName2"));// 获取页面标题String title = driver.getTitle();// 验证当前页面标题信息assert title.equals("在线音乐列表");}// 检查音乐的查询功能public void selectMusic() {WebElement input = driver.findElement(By.cssSelector("#exampleInputName2"));input.sendKeys("李宇春 - 咏春");WebElement select = driver.findElement(By.cssSelector("#submit1"));select.click();List<WebElement> result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() == 1;input.clear();input.sendKeys("南征北战");select.click();result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() >= 1;input.clear();select.click();result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() >= 1;input.clear();input.sendKeys("没有这个音乐");select.click();result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() == 0;input.clear();}// 检查删除选中音乐的功能public void deleteSelMusic() {driver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("");driver.findElement(By.cssSelector("#submit1")).click();List<WebElement> result = driver.findElements(By.cssSelector("#info > tr"));int i = result.size();if (i > 10) {driver.findElement(By.cssSelector("#\\31 " + (i % 10 - 1))).click();}else {driver.findElement(By.cssSelector("#\\3" + (i - 1))).click();}driver.findElement(By.cssSelector("#delete")).click();wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();assert alert.getText().equals("音乐全部删除成功! ");alert.accept();i--;driver.navigate().refresh();int count = 3;assert count <= i;while (count > 0 && i > 10) {driver.findElement(By.cssSelector("#\\31 " + (i % 10 - 1))).click();i--;count--;}while (count > 0) {driver.findElement(By.cssSelector("#\\3" + (i - 1))).click();i--;count--;}driver.findElement(By.cssSelector("#delete")).click();wait.until(ExpectedConditions.alertIsPresent());assert alert.getText().equals("音乐全部删除成功! ");alert.accept();driver.findElement(By.cssSelector("#delete")).click();wait.until(ExpectedConditions.alertIsPresent());assert alert.getText().equals("批量删除音乐失败!! ");alert.accept();}// 检查删除音乐的功能public void deleteMusic() {driver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("");driver.findElement(By.cssSelector("#submit1")).click();int index = driver.findElements(By.cssSelector("#info > tr")).size();driver.findElement(By.cssSelector("#del" + (index - 1))).click();wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();assert alert.getText().equals("删除音乐成功! ");alert.accept();}// 检查喜欢音乐的功能public void loveMusic() {driver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("");driver.findElement(By.cssSelector("#submit1")).click();int index = driver.findElements(By.cssSelector("#info > tr")).size();driver.findElement(By.cssSelector("#love" + (index - 1))).click();wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();assert alert.getText().equals("喜欢成功! ");alert.accept();}
}
(5)创建喜欢列表测试用例类
创建 LovePage 类,在这里编写喜欢列表页面的所有测试用例,在这里我们要完成的事情如下:
- 检查喜欢列表页面是否能正确加载;
- 检查喜欢音乐的查询功能是否正常;
- 检查取消喜欢音乐的功能是否正常;
- 检查回到大厅的按钮功能是否正常。
有关 LovePage 类的具体代码及详细介绍如下所示:
public class LovePage extends Utils {// 指定页面的 URLprivate static String url = "http://127.0.0.1:8080/loveMusic.html";// 设置显式等待private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));public LovePage() {super(url);}// 检查页面是否正确加载public void lovePageRight() {driver.findElement(By.cssSelector("body > div.container > div:nth-child(3) > a"));String title = driver.getTitle();assert title.equals("喜欢音乐列表");}// 检查喜欢音乐查询功能public void selLoveMusic() {WebElement input = driver.findElement(By.cssSelector("#exampleInputName2"));input.sendKeys("李宇春 - 咏春");WebElement select = driver.findElement(By.cssSelector("#submit1"));select.click();List<WebElement> result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() == 1;input.clear();input.sendKeys("无涯");select.click();result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() >= 1;input.clear();select.click();result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() >= 1;input.clear();input.sendKeys("没有这个音乐");select.click();result = driver.findElements(By.cssSelector("#info > tr"));assert result.size() == 0;input.clear();}// 检查取消喜欢音乐功能public void delLoveMusic() throws InterruptedException {driver.findElement(By.cssSelector("#exampleInputName2")).sendKeys("");driver.findElement(By.cssSelector("#submit1")).click();int index = driver.findElements(By.cssSelector("#info > tr")).size();driver.findElement(By.cssSelector("#del0")).click();wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();assert alert.getText().equals("取消喜欢音乐成功!");alert.accept();}// 检查回到大厅的按钮功能public void loveBack() {driver.findElement(By.cssSelector("body > div.container > div:nth-child(3) > a")).click();String title = driver.getTitle();assert title.equals("在线音乐列表");}
}
(6)创建上传音乐测试用例类
创建 UploadPage 类,在这里编写上传音乐页面的所有测试用例,在这里我们要完成的事情如下:
- 检查上传音乐页面是否能正确加载;
- 检查上传音乐的功能是否正常;
- 检查回到首页的连接跳转功能是否正常。
有关 UploadPage 类的具体代码及详细介绍如下所示:
public class UploadPage extends Utils {// 指定页面的 URLprivate static String url = "http://127.0.0.1:8080/upload.html";// 设置显式等待private WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));public UploadPage() {super(url);}// 检查页面正确加载public void uploadPageRight() {// 查找是否有歌手输入框driver.findElement(By.cssSelector("#singerInput"));driver.findElement(By.cssSelector("#fileInput"));String title = driver.getTitle();assert title.equals("上传音乐");}// 检查上传音乐功能public void uploadMusic() throws InterruptedException {driver.findElement(By.cssSelector("#fileInput")).sendKeys("D:\\音乐下载\\李宇春 - 咏春.mp3");driver.findElement(By.cssSelector("#singerInput")).sendKeys("李宇春");driver.findElement(By.cssSelector("#uploadFrom > input[type=submit]:nth-child(3)")).click();wait.until(ExpectedConditions.alertIsPresent());Alert alert = driver.switchTo().alert();assert alert.getText().equals("已经拥有当前歌曲! ");alert.accept();driver.navigate().refresh();driver.findElement(By.cssSelector("#fileInput")).sendKeys("D:\\音乐下载\\庞龙 - 兄弟抱一下 [mqms2].mp3");driver.findElement(By.cssSelector("#singerInput")).sendKeys("庞龙");driver.findElement(By.cssSelector("#uploadFrom > input[type=submit]:nth-child(3)")).click();wait.until(ExpectedConditions.alertIsPresent());assert alert.getText().equals("音乐上传成功! ");alert.accept();String title = driver.getTitle();assert title.equals("在线音乐列表");}// 检查返回首页的功能public void uploadBack() {driver.get(url);driver.findElement(By.cssSelector("#uploadFrom > a")).click();String title = driver.getTitle();assert title.equals("在线音乐列表");}}
(7)创建运行测试用例类
创建 RunTest 类, 在这里进行所有测试代码的运行,我们要以合理的方式调用每一个页面的所有测试方法,来进行在线音乐播放器的 UI 自动化测试,关于 RunTest 的具体代码及详细介绍如下所示:
public class RunTest {public static void main(String[] args) throws InterruptedException {// 1. 运行登录页面的测试用例自动化测试方法LoginPage loginPage = new LoginPage();loginPage.loginPageRight();loginPage.loginFail();loginPage.loginSuc();// 2. 运行上传音乐页面的测试用例自动化测试方法UploadPage uploadPage = new UploadPage();uploadPage.uploadPageRight();uploadPage.uploadMusic();uploadPage.uploadBack();// 3. 运行喜欢列表页面的测试用例自动化测试方法LovePage lovePage = new LovePage();lovePage.lovePageRight();lovePage.selLoveMusic();lovePage.delLoveMusic();lovePage.loveBack();// 4. 运行列表页面的测试用例自动化测试方法ListPage listPage = new ListPage();listPage.listPageRight();listPage.selectMusic();listPage.loveMusic();listPage.deleteMusic();listPage.deleteSelMusic();// 5. 释放 driver 对象Utils.driver.quit();}
}
3.自动化测试执行结果
我们在 RunTest 类中进行运行,运行的过程及结果如下图所示:
如上图运行过程所示,我们的自动化测试用例全部通过,在执行自动化测试的时候,我们要注意多次执行的时候,在上传音乐的方法中要更改新的上传音乐,否则就会上传音乐失败,在执行失败的时候要多用屏幕截图来抓取当时出错的场景。
五、性能测试
下面我来使用 JMeter 对在线音乐播放器项目的登录接口和获取音乐列表接口及获取喜欢音乐列表接口进行简单的性能测试,下面就来介绍在线音乐播放器项目性能测试的一个测试流程。
1.创建梯度压测线程组
这里我们创建一个梯度压测线程组(Stepping Thread Group),来慢慢增大我们对这两个接口的并发请求的数量,创建的梯度压测线程组的具体配置如下图所示:
2.创建 HTTP 请求默认值
在在线音乐播放器项目中涉及到的接口协议、IP、端口号及内容编码都完全一样,所以我们就可以把这些单独抽取出来,存放在默认值中,这样其他接口就可以省略不写协议、IP、端口号及内容编码了,这里我们具体设置的默认值如下图所示:
3.创建 HTTP Cookie 管理器
如果我们在未登录状态进行获取音乐列表的操作,将会获取到一个空的音乐列表,这显然是不科学的,所以为了我们可以获取到登录请求中用户的用户信息就需要添加一个 HTTP Cookie 管理器,它会像浏览器一样存储和发送 Cookie ,如果我们 HTTP 请求返回的响应中包含 Cookie 那么 Cookie 管理器就会自动存储该 Cookie,并把这个 Cookie 用于后面特定的请求中,所以添加了 HTTP Cookie 管理器后,就会自动存储并发送 Cookie,添加的管理器如下图所示:
4.创建音乐播放器登录请求
根据在线音乐播放器项目中用户登录的接口来编写用户登录请求的内容,具体内容如下图所示:
5.创建获取音乐列表页请求
根据在线音乐播放器项目中获取音乐列表请求接口来编写获取音乐列表的内容,具体内容如下图所示:
6.创建获取喜欢音乐列表页请求
根据在线音乐播放器项目中获取喜欢音乐列表请求接口来编写获取喜欢音乐列表的内容,具体内容如下图所示:
7.性能测试执行结果
执行性能测试之前,我们添加以下四个监听器,它们的用途如下所示:
- Active Thread Over Time:这是用来记录每一时刻存活线程的数目,最后形成一个图表;
- Transactions per Second(TPS):这个监听器是用来分析系统吞吐量的重要工具。TPS 即每秒事务数,表示一个客户机向服务器发送请求后服务器做出反应的过程,这个指标反映了系统在同一时间内处理业务的最大能力,TPS 越高,说明系统的处理能力越强。
- Response Times Over Time:这个监听器是用来监听整个事务运行期间的响应时间,在测试过程中,它可以帮我们观察并分析响应时间的实时平均值以及整体响应时间的走向,通过这个监听器,我们可以更直观的了解系统中不同时间点的响应性能,从而发现可能存在的性能问题;
- 聚合报告:通过这个报告,可以看到性能测试过程中整体的数据变化。
下面我们开始执行性能测试,关于各监听器执行后的结果,如下图所示:
8.生成性能测试报告
执行完成性能测试之后,我们需要出具一份性能测试报告,这个报告不用我们手动进行编写,而是通过命令的方式使用 JMeter 来自动帮我们生成,具体操作如下图所示:
关于上图中命令所涉及参数的含义,具体介绍如下所示:
- -n:以无图形化运行;
- -t:被运行的脚本;
- -l:将运行信息写入日志文件,后缀为 jtl 的日志文件;
- -e:生成测试报告;
- -o:指定报告输出目录。
注意:日志文件和目录可以不存在,若已经存在,要保证内容为空,否则会出现错误。
那么测试报告生成之后,在 网页版五子棋性能测试报告 文件夹下将出现如下图所示的内容:
双击 index.html 文件,界面展示如下:
关于性能测试报告的具体内容我在这里就不进行过多展示了,感兴趣的小伙伴我会把这个报告附在本篇文章中,可以自行观察。
·总结
文章到此就要结束了,在这里我再对本篇测试报告做一个总结,我们一共进行了功能测试、自动化测试以及性能测试这三种测试方式,在功能测试阶段,我们着重点是对项目整体进行了一个简易的测试;在自动化测试阶段,我们主要测试各个页面的相关信息,着重测试了登录及音乐列表页面的相关功能;在性能测试阶段,我们着重测试了用户登录、获取用音乐列表、获取喜欢音乐列表的接口性能,并生成了性能测试报告,在以上过程中,遇到的问题就是执行自动化测试时会出现上传音乐失败的情况,这是因为我们每次运行自动化测试脚本时,都需要更改上传音乐的信息,否则就会出现音乐已经存在的情况,还有就是性能测试中,获取音乐列表及获取喜欢音乐列表为空,解决方式就是添加 HTTP Cookie 管理器,如果对文章内容有所疑惑,欢迎在评论区进行留言,如果感觉本篇文章还不错希望能收到你的三连支持,那么我们下一篇文章再见吧~~~
相关文章:
在线音乐播放器 —— 测试报告
自动化脚本源代码:Java: 利用Java解题与实现部分功能及小项目的代码集合 - Gitee.com 目录 前言 一、项目简介 1.项目背景 2.应用技术 (1)后端开发 (2)前端开发 (3)数据库 二、项目功能…...
6.算法移植第六篇 YOLOV5/rknn生成可执行文件部署在RK3568上
接上一篇文章best-sim.rknn模型生成好后,我们要将其转换成可执行文件运行在RK3568上,这一步需要在rknpu上进行,在强调一遍!!rknpu的作用是可以直接生成在开发板上运行的程序 退出上一步的docker环境 exit1.复制best-…...
【贪心算法第七弹——674.最长连续递增序列(easy)】
目录 1.题目解析 题目来源 测试用例 2.算法原理 3.实战代码 代码分析 1.题目解析 题目来源 674.最长递增子序列——力扣 测试用例 2.算法原理 贪心思路 3.实战代码 class Solution { public:int findLengthOfLCIS(vector<int>& nums) {int n nums.size();in…...
剖析前后端 API 接口参数设计:JSON 数据结构化全攻略
在当今软件开发领域,前后端分离架构已成为主流趋势。而 API 接口作为前后端之间数据交互的桥梁,其设计的合理性对系统的可维护性和扩展性起着至关重要的作用。JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式&…...
【RISC-V CPU debug 专栏 2.3 -- Run Control】
文章目录 Run ControlHart 运行控制状态位状态信号操作流程时间与实现注意事项Run Control 在 RISC-V 调试架构中,运行控制模块通过管理多个状态位来对硬件线程(harts)的执行进行调节和控制。这些状态位帮助调试器请求暂停或恢复 harts,并在 hart 复位时进行控制。以下是运…...
力扣887:鸡蛋掉落问题
题目描述: 给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。 已知存在楼层 f ,满足 0 < f < n ,任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。…...
Matlab与python数据处理对比
MATLAB 和 Python 都是数据分析和科学计算中常用的编程语言,各自有其优点和应用场景。它们在数据处理方面有许多相似之处,但也有一些关键差异。以下是 MATLAB 和 Python 在数据处理方面的对比与总结。 ### 1. **语法与语言特性** - **MATLAB**: - 以…...
【系统架构设计师】高分论文:论软件架构的生命周期
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 摘要正文摘要 2022 年5月,本人所在的某集团公司承接了财务共享服务平台综合管理系统的项目开发,该项目主要实现财务系统主流业务的集成共享。本人担任项目组成员中的系统架构设计师一职,全面负责项目的全生命周…...
gitlab工作笔记
gitlab常用操作 gitlab常用笔记docker 安装模式pull imagerun一个gitlab container atttach入containerdocker run 之后要等几分钟安装之后的初始配置初始密码在哪里 :第一次登录创建和检查第一个工程能否正常clone gitlab常用笔记 装过几次gitlab,但每…...
shell完结
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
优维HAO案例:全球TOP15汽车零件供应商「IT运维自动化」创新工程
撰文:鹿小U / 制图:脾气超好 又是一家很厉害的客户。 YADT是全(hu)球(zhēn)领(ji)先(sh)的汽车座椅供应商,拥有从汽车座椅零部件到整椅的完整生产制造能力,为中国几乎所有的汽车制造商提供汽车整椅产品和服务。 YADT在国内拥…...
语义版本控制
注意: 本文内容于 2024-11-27 22:25:05 创建,可能不会在此平台上进行更新。如果您希望查看最新版本或更多相关内容,请访问原文地址:语义版本控制。感谢您的关注与支持! 由于自己平时喜欢写点小玩意,自然而…...
C++设计模式行为模式———策略模式
文章目录 一、引言二、策略模式三、总结 一、引言 策略模式是一种行为设计模式, 它能让你定义一系列算法, 并将每种算法分别放入独立的类中, 以使算法的对象能够相互替换。与模板方法模式类似,都是以扩展的方式来支持未来的变化。…...
Pgsql:json字段查询与更新
1.查询json字段的值 SELECT attribute_data->>设施类别 mycol, * FROM gis_coord_data WHERE attribute_data->>设施类别阀门井 查询结果如下: 2.更新json字段中的某个属性值 UPDATE gis_coord_data SET attribute_data(attribute_data::jsonb ||{&quo…...
鸿蒙面试 --- 性能优化
性能优化可以从三个方面入手 感知流畅、渲染性能、运行性能 感知流畅 在应用开发中,动画可以为用户界面增添生动、流畅的交互效果,提升用户对应用的好感度。然而,滥用动画也会导致应用性能下降,消耗过多的系统资源,…...
【逐行注释】自适应观测协方差R的AUKF(自适应无迹卡尔曼滤波,MATLAB语言编写),附下载链接
文章目录 自适应R的UKF逐行注释的说明运行结果部分代码各模块解释 自适应R的UKF 自适应无迹卡尔曼滤波(Adaptive Unscented Kalman Filter,AUKF)是一种用于状态估计的滤波算法。它是基于无迹卡尔曼滤波(Unscented Kalman Filter&…...
mac下安装Ollama + Open WebUI + Llama3.1
本文介绍mac下安装Ollama Open WebUI Llama3.1 8b具体步骤。 目录 推荐配置Ollama Open WebUI Llama3.1简介安装Ollama安装Open WebUI 推荐配置 m1以上芯片,16g内存,20g以上硬盘空间 Ollama Open WebUI Llama3.1简介 Ollama: 下载,管理…...
Python Tornado框架教程:高性能Web框架的全面解析
Python Tornado框架教程:高性能Web框架的全面解析 引言 在现代Web开发中,选择合适的框架至关重要。Python的Tornado框架因其高性能和非阻塞I/O特性而备受青睐。它特别适合处理大量并发连接的应用,比如聊天应用、实时数据处理和WebSocket服务…...
QT-installEventFilter
installEventFilter 是 Qt 框架中的一个方法,用于在对象之间建立事件过滤机制。具体来说,它允许一个对象(称为事件过滤器)监视另一个对象(称为被监视对象)的事件,并在这些事件被处理之前对其进行…...
ZYNQ详解
ZYNQ是Xilinx公司推出的一系列SoC(System-on-Chip,系统级芯片)产品家族,它将传统的FPGA(可编程逻辑器件)与嵌入式处理器相结合,形成了一种集成了硬件和软件处理能力的单一芯片解决方案。以下是对…...
代码随想录打卡DAY21
算法记录第21天 [二叉树] 1.LeetCode 538. 把二叉搜索树转换为累加树 题目描述: 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原…...
LeetCode【代码随想录】刷题(数组篇)
704.二分查找 力扣题目链接 题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 思路:简单的二…...
Python知识第十二天分享
假设有一个文件 num.txt,里面存储了如下的一些数字,内容如下: 10 18 30 11 12 15 编写一个 python 程序,读取文件中的内容,存储成 python 中的列表形式: sum 0 with open(./num.txt, r) as nu_f:list1 …...
[SWPUCTF 2021 新生赛]easy_md5
借鉴博客 [SWPUCTF 2021 新生赛]easy_md5_青少年ctf easymd5-CSDN博客 我们直接看见源码 <?php highlight_file(__FILE__);include flag2.php;if (isset($_GET[name]) && isset($_POST[password])){$name $_GET[name];$password $_POST[password];if ($name …...
C# 开发应用篇——C# 基于WPF实现数据记录导出excel详解
目录 引言 一、基于 EPPlus 库实现WPF导出EXCEL功能 项目准备 创建 WPF 界面 后端代码 EPPlus LicenseContext 属性设置 关键点说明 二、基于 ClosedXML 库实现WPF导出EXCEL功能 安装 ClosedXML 使用 ClosedXML 创建和操作 Excel 文件 读取 Excel 文件 常…...
MongoDB相关问题
视频教程 【GeekHour】20分钟掌握MongoDB Complete MongoDB Tutorial by Net Ninja MongoDB开机后调用缓慢的原因及解决方法 问题分析: MongoDB开机后调用缓慢,通常是由于以下原因导致: 索引重建: MongoDB在启动时会重建索引…...
从入门到精通数据结构----四大排序(上)
目录 首言: 1. 插入排序 1.1 直接插入排序 1.2 希尔排序 2. 选择排序 2.1 直接选择排序 2.2 堆排序 3. 交换排序 3.1 冒泡排序 3.2 快排 结尾: 首言: 本篇文章主要介绍常见的四大排序:交换排序、选择排序、插入排序、归并排…...
数据结构-堆的实现和应用
目录 1.堆的概念 2.堆的构建 3.堆的实现 4.堆的功能实现 4.1堆的初始化 4.2堆的销毁 4.3堆的插入 4.3.1向上调整 4.4堆的删除 4.4.1向下调整法 编辑4.5取堆顶 5. 向上调整法和向下调整法比较 6.堆的应用 6.1TOP-K问题 6.2TOP-K思路 6.2.1用前n个数据来建堆 6.…...
Spring MVC
1. 用户发起请求 用户行为:用户在浏览器中输入URL或点击链接,向Web服务器(如Tomcat)发起一个HTTP请求。请求传输:请求被发送到Web容器,Web容器根据配置将请求转发给DispatcherServlet。 2. 前端控制器&am…...
linux ubuntu的脚本知
目录 一、变量的引用 二、判断指定的文件是否存在 三、判断目录是否存在 四、判断最近一次命令执行是否成功 五、一些比较符号 六、"文件"的读取和写入 七、echo打印输出 八、ubuntu切换到root用户 九、后台进程的控制 N、其它可以参考的网址 脚本功能强大…...
Spring Boot 动态数据源切换
背景 随着互联网应用的快速发展,多数据源的需求日益增多。Spring Boot 以其简洁的配置和强大的功能,成为实现动态数据源切换的理想选择。本文将通过具体的配置和代码示例,详细介绍如何在 Spring Boot 应用中实现动态数据源切换,帮…...
Design Linear Filters in the Frequency Domain (MATLAB帮助文档)
Design Linear Filters in the Frequency Domain 这个帮助文档写得很好,简单明了,一句废话没有。 This topic describes functions that perform filtering in the frequency domain. 2-D Finite Impulse Response (FIR) Filters The Image Processi…...
Java知识及热点面试题总结(二)
1、什么是死锁(deadlock)? 两个线程或两个以上线程都在等待对方执行完毕才能继续往下执行的时候就发生了死锁。结果就是这些线程都陷入了无限的等待中。 如何避免线程死锁? 只要破坏产生死锁的四个条件中的其中一个就可以了。 破坏互斥条件:这个条件我们没有办法…...
开源加密库mbedtls及其Windows编译库
目录 1 项目简介 2 功能特性 3 性能优势 4 平台兼容性 5 应用场景 6 特点 7 Windows编译 8 编译静态库及其测试示例下载 1 项目简介 Mbed TLS是一个由ARM Maintained的开源项目,它提供了一个轻量级的加密库,适用于嵌入式系统和物联网设备。这个项…...
架构01-演进中的架构
零、文章目录 架构01-演进中的架构 1、原始分布式时代:Unix设计哲学下的服务探索 (1)背景 时间:20世纪70年代末到80年代初计算机硬件:16位寻址能力、不足5MHz时钟频率的处理器、128KB左右的内存转型:从…...
npm-运行项目报错:A complete log of this run can be found .......npm-cache_logs\
1.问题 没有找到对应的某种依赖,node_modules出现问题。 2.解决 (1)查看对应依赖是否引入或者是由于合并分支错误 引入js或依赖不存在。谨慎删除依赖包 (2)查找对应引入依赖进行安装最后解决方法-删除依赖包清除缓存 npm cache clean --force (2)重新向同事引入…...
C++中的函数对象
C 中函数对象的定义和特点 定义:函数对象(Function Object)也叫仿函数(Functor),是一个类,这个类重载了函数调用运算符()。当创建这个类的对象后,可以像使用函数一样使用这个对象&am…...
godot游戏引擎_瓦片集和瓦片地图介绍
在 Godot 中,TileSet 和 TileMap 是用于处理瓦片地图的两个关键概念,它们的作用和用途有明显的区别。以下是两者的详细对比: 1. TileSet(瓦片集) TileSet 是资源,定义瓦片的内容和属性。 特点:…...
[C++ 核心编程]笔记 4.1 封装
4.1.1 封装的意义 封装是C面向对象三大特性之一 封装的意义: 将属性和行为作为一个整体,表现生活中的事物将属性和行为加以权限控制 封装意义一: 在设计类的时候,属性和行为写在一起,表现事物 语法: class 类名{ 访问权限: 属性 /行为 }…...
学习使用jquery实现在指定div前面增加内容
学习使用jquery实现在指定div前面增加内容 设计思路代码示例 设计思路 选择要添加内容的指定元素: 使用jQuery选择器来选择你希望在其前添加内容的元素。例如,如果你有一个 元素,其ID为qipa250,你可以使用$(‘#qipa250’)来选择…...
如何写出好证明(支持思想的深入数学写作)
不断的修改和精炼是写作过程中的重要环节,数学写作最终目的是提供对问题的深刻洞察而非仅仅陈述细节。 根据harvey mudd college Francis Su教授的《GUIDELINES FOR GOOD MATHEMATICAL WRITING》讲稿,总结出撰写好的数学证明需要注意以下几个要点&#x…...
基于边缘智能网关的机房安全监测应用
随着我国工业互联网的扎实推进,越来越多地区积极建设信息基础设施,以充沛算力支撑产业物联网的可持续发展,数据机房就是其中的典型代表。而且随着机房规模的扩大,对于机房的安全管理难题挑战也日益增加。 面向数据机房安全监测与管…...
在WSL 2 (Ubuntu 22.04)安装Docker Ce 启动错误解决
查看WSL版本 在 Windows 命令提示符(CMD)或 PowerShell 中,你可以使用以下命令来查看已安装的 WSL 发行版及其版本信息: wsl -l -v(base) PS C:\Users\Lenovo> wsl -l -vNAME STATE VERSION * Ubuntu-2…...
【RISC-V CPU debug 专栏 3 -- Debugging RISC-V Cores】
文章目录 RISC-V 调试规范开源与多样性挑战调试规范的重要性外部调试支持的主要组件调试功能Lauterbach 的贡献RISC-V 调试规范 调试 RISC-V 内核涉及许多独特的挑战,这是由 RISC-V 的开源特性和多样化的生态系统所决定的。为了避免专有调试接口的泛滥,RISC-V 基金会内的工作…...
Unity Banner广告后面自定义背景,高度适配
目的是实现这个,代码放下面 已经测试十几台设备包括pad没问题 以Max聚合为例 展示(关闭)Banner的时候调用Show,Banner加载成功回调里调用RefreshSizeDelta 最终获得是像素 所以UGUI的Canvas使用Constant Pixel Size模式࿰…...
【技术文档:技术传播的灯塔】
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
git的使用(简洁版)
什么是 Git? Git 是一个分布式版本控制系统 (DVCS),用于跟踪文件的更改并协调多人之间的工作。它由 Linus Torvalds 在 2005 年创建,最初是为了管理 Linux 内核的开发。Git 的主要目标是提供高效、易用的版本控制工具,使得开发者…...
数据库编程(sqlite3)
一:数据库分类 常用的数据库 大型数据库 :Oracle商业、多平台、关系型数据库功能最强大、最复杂、市场占比最高的商业数据库 中型数据库 :Server是微软开发的数据库产品,主要支持windows平台 小型数据库 : mySQL是一个小型关系型…...
Python 中如何处理异常?
在Python中,异常处理是一种重要的编程技术,它允许开发者优雅地处理程序运行过程中出现的错误或异常情况,而不是让程序直接崩溃。 通过异常处理,我们可以使程序更加健壮、用户友好。 异常处理的基本结构 Python中最基本的异常处…...
RHCE——nfs网络文件系统
简介 NFS(Network File System,网络文件系统)是FreeBSD支持的文件系统中的一种,它允许网络中的计算机(不同的计算机、不同的操作系统)之间通过TCP/IP网络共享资源,主要在unix系列操作系统上使用…...