当前位置: 首页 > news >正文

【项目】论坛系统测试

在这里插入图片描述

文章目录

  • 一、项目介绍
  • 二、测试环境
  • 三、测试用例
    • 3.1 论坛系统功能测试用例
    • 3.2 论坛系统非功能测试用例
  • 四、测试计划
    • 1. 手工测试
      • 1.1 注册页面
      • 1.2 登陆页面
      • 1.3 主页面(列表页)
    • 2. 自动化测试
      • 2.1 添加对应的依赖
      • 2.2 Utils类(公有类)
      • 2.3 RegisterPage类 (注册页面)
      • 2.4 LoginPage 类(登录页面)
      • 2.5 PageByNoLogin 类 (未登录页面)
      • 2.6 ListPage 类 (主页面/列表页)
      • 2.7 RunTest 类(测试运行)
    • 3. 性能测试
      • 3.1 HTTP请求默认值
      • 3.2 CSV数据文件设置
      • 3.3 梯度压测

一、项目介绍

论坛系统是采用前后端分离的方式实现的,使用到的技术有:SpringBoot,SpringMVC,MyBatis,MySQL等,并将其部署到了云服务器上。系统旨在为用户提供一个基于 Web 的文章发布和讨论平台。用户可以进行注册登录、查看和修改个人信息,以及进行帖子的增删改查等基础操作。此外,系统还提供了评论、站内信等交流功能,用户可以对帖子进行点赞,并在帖子详情页上查看阅读量、点赞数、评论量等信息。

二、测试环境

  • 硬件: LAPTOP-C2IIA694 (i7 10710U/16GB/512GB/MX250)
  • 操作系统: Windows11(专业版)
  • 浏览器: 129.0.6668.100(正式版本) (64 位)
  • 测试工具: 自动化测试Selenium,性能测试Jmeter
  • 自动化脚本运行环境: IntelliJ IDEA Community Edition 2022.3.3

三、测试用例

3.1 论坛系统功能测试用例

在这里插入图片描述

3.2 论坛系统非功能测试用例

在这里插入图片描述

四、测试计划

1. 手工测试

注:手工测试仅执行部分测试用例

1.1 注册页面

测试用例一:
用户名,昵称,密码以及确认密码均为必填,未填写完整,点击注册按钮
预期结果:页面提示该信息不能为空
实际结果:页面给出相应提示与预期结果一致
在这里插入图片描述

测试用例二:
输入用户名在数据库中已存在,点击注册按钮
预期结果:页面给出相应提示该用户已存在
实际结果:页面给出相应提示与预期结果一致

在这里插入图片描述
测试用例三:
输入用户名在数据库中不存在,密码和确认密码不一致,点击注册按钮
预期结果:页面给出相应提示该请检查确认密码
实际结果:页面给出相应提示与预期结果一致
在这里插入图片描述

测试用例四:
输入用户名在数据库中不存在,密码和确认密码一致,未勾选同意使用条款和隐私政策,点击注册按钮
预期结果:页面给出相应提示勾选框和同意字体为红色
实际结果:页面给出相应提示与预期结果一致
在这里插入图片描述

测试用例五:
输入的用户名数据库中不存在,昵称不为空,密码与确认密码一致并且勾选同意使用条款和隐私政策,点击注册按钮
预期结果:页面显示注册成功,并跳转回登录界面。
实际结果:页面显示注册成功并跳转至登陆界面与预期结果一致
在这里插入图片描述
在这里插入图片描述

1.2 登陆页面

测试用例一:
输入已存在的用户名,并且密码正确
预期结果:登录成功并跳转至列表页
实际结果:登录成功并跳转至列表页与预期结果一致

在这里插入图片描述
在这里插入图片描述
测试用例二:
账号为空/密码为空
预期结果:页面给出相应提示用户名不能为空/密码不能为空
实际结果:页面给出相应提示与预期结果一致
在这里插入图片描述

在这里插入图片描述
测试用例三:
账号为空密码不为空但账号密码错误
预期结果:页面给出相应提示用户名或密码错误
实际结果:页面给出相应提示与预期结果一致

在这里插入图片描述

1.3 主页面(列表页)

首页

  • 测试用例一:
    未登录状态下,打开列表页
    预期结果:跳转回登录界面
    实际结果:跳转回登录界面,与预期结果一致

  • 测试用例二:
    登录状态下,打开列表页
    预期结果:第一行论坛名和论坛logo,同行有搜索框,昼夜调节,消息,用户头像,下一行是导航栏显示所有版块名,各个板块均可点击,接下来左边是首页二字,左边是发布帖子按钮,下面是当前论坛的所有帖子。
    实际结果:页面加载成功,与预期结果一致
    在这里插入图片描述

  • 测试用例三:
    登录状态下,在搜索框输入关键字“Java”搜索
    预期结果:下方显示帖子正文中所有存在“Java”这三个字的帖子;
    实际结果:刷新回到首页界面,与预期不符。不支持搜索功能

  • 测试用例四:
    登录状态下,点击页面小月亮图标
    预期结果:可以实现昼夜调节
    实际结果:页面与预期结果一致

  • 测试用例五:
    登录状态下,点击消息模块
    预期结果:导航栏点击小铃铛显示当前所有私信,未读用文字和红色小圆点标识,已读用文字和灰色小圆点表示,已回复用文字和绿色小圆点标识
    实际结果:页面与预期结果一致
    在这里插入图片描述

  • 测试用例六:
    登录状态下,点击发布帖子按钮并测试板块下拉框
    预期结果:板块名默认选择Java并且下拉框正常
    实际结果:页面与预期结果一致
    在这里插入图片描述

  • 测试用例七:
    登录状态下,点击用户
    预期结果:出现我的帖子,个人中心,退出等选项
    实际结果:页面加载与预期结果一致
    在这里插入图片描述

我的帖子

  • 测试用例一:
    登录状态下,点击用户->我的帖子
    预期结果:出现个人头像,昵称,发帖数,邮箱,简介以及个人帖子等信息
    实际结果:页面加载与预期结果一致
    在这里插入图片描述
  • 测试用例二:
    登录状态下,点击用户->我的帖子->点击第一篇帖子
    预期结果:会出现帖子标题,个人头像昵称,帖子内容,点赞编辑删除按钮及回复框
    实际结果:页面加载与预期结果一致
    在这里插入图片描述
  • 测试用例三:
    登录状态下,点赞
    预期结果:页面右下角出现提示点赞成功
    实际结果:页面与预期结果一致
    在这里插入图片描述
  • 测试用例四:
    登录状态下,点击编辑帖子,清空内容直接点提交
    预期结果:页面右下角出现提示请输入帖子内容
    实际结果:页面与预期结果一致
    在这里插入图片描述
    …(手工测试仅测试部分测试用例)

个人中心

  • 测试用例一:
    登录状态下,点击用户->个人中心
    预期结果:下方显示该登录用户的所有信息
    实际结果:页面与预期结果一致
    在这里插入图片描述
  • 测试用例二:
    登录状态下,修改头像
    预期结果:打开 电脑,上传本地图片并更新头像。
    实际结果:打开电脑,上传本地图片,但是没有反应。与预期不符(不支持修改头像)。
  • 测试用例三:
    登录状态下,修改昵称
    预期结果:修改成功,右下角出现提示操作成功
    实际结果:页面与预期结果一致在这里插入图片描述
  • 测试用例四:
    原密码正确,新密码和确认密码不一致,修改失败,给出错误提示
    预期结果:修改失败,页面右下角出现提示两次密码输入不相同
    实际结果:页面与预期结果一致
    在这里插入图片描述
    …(手工测试仅测试部分测试用例)

2. 自动化测试

自动化测试码云链接:FourmAutoTest

2.1 添加对应的依赖

  1. 先添加对应的依赖
   <dependencies><dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.8.0</version></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.0.0</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency></dependencies>

在这里插入图片描述
2. 定义两个包common里放公共方法类,tests包里放各个页面的测试,运行类RunTest放在两个包外
在这里插入图片描述

2.2 Utils类(公有类)

公有类:创建driver对象,测试过程中屏幕截图的通用工具类

package common;import io.github.bonigarcia.wdm.WebDriverManager;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
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;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统公共方法*/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();//访问urldriver.get(url);//窗口最大化driver.manage().window().maximize();}//屏幕截图public void getScreenShot(String str) throws IOException, IOException {//     ./src/test/image///                     /2024-07-17///                                /test01-17453010.png//                                /test02-17453020.png//                     /2024-07-18///                                /test01-17453030.png//                                /test02-17453034.png//屏幕截图SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");String dirTime = sim1.format(System.currentTimeMillis());String fileTime = sim2.format(System.currentTimeMillis());//./src/test/image/2024-07-17/test01-17453020.pngString filename ="./src/test/image/"+ dirTime +"/" + str + "-" + fileTime+".png";File srcFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);//srcFile放到指定位置FileUtils.copyFile(srcFile,new File(filename));}}

2.3 RegisterPage类 (注册页面)

测试注册页面的加载,注册成功和注册成功

package tests;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统注册页面* Author: WJW*/
public class RegisterPage extends Utils {public static String url = "http://127.0.0.1:9580/sign-up.html";public RegisterPage() {super(url);}public void RegisterPageRight() {//论坛logo图标driver.findElement(By.cssSelector("body > div > div > div.text-center.mb-4 > img"));//用户注册driver.findElement(By.cssSelector("#signUpForm > div > h2"));}//注册成功public void RegisterSuc() throws InterruptedException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("橘子004");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("橘子树0");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000);//校验注册是否成功并返回登录页面String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}//注册失败01--该用户已存在public void RegisterFai01() throws IOException {//在登录页面点击注册按钮// 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("1");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务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();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail01.equals("警告");}//注册失败02--用户名为空public void RegisterFai02() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名 当前用户名为空driver.findElement(By.cssSelector("#username"));//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("1");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail02 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(2) > div")).getText();//对当前异常进行截图getScreenShot(getClass().getName());//断言assert fail02.equals("用户名不能为空");}//注册失败03--昵称为空public void RegisterFai03() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("1");//输入昵称 当前昵称为空driver.findElement(By.cssSelector("#nickname"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail03 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(3) > div")).getText();//截图保存当前异常getScreenShot(getClass().getName());//断言assert fail03.equals("昵称不能为空");}//注册失败04--密码与确认密码不一致public void RegisterFai04() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("13");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy")).click();//点击注册driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String fail04 = driver.findElement(By.cssSelector("#signUpForm > div > div:nth-child(5) > div > div")).getText();getScreenShot(getClass().getName());assert fail04.equals("请检查确认密码");}//注册失败05--未点击同意使用条款和隐私服务public void RegisterFai05() throws IOException {//刷新当前注册页面driver.navigate().refresh();//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("101");//输入昵称driver.findElement(By.cssSelector("#nickname")).sendKeys("111");;//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys("123");//未点击同意使用条款和隐私服务driver.findElement(By.cssSelector("#policy"));//点击注册driver.findElement(By.cssSelector("#submit")).click();//截图保存当前异常getScreenShot(getClass().getName());}}

2.4 LoginPage 类(登录页面)

测试登录页面的加载,登录成功和登录失败

package tests;import common.Utils;
import org.openqa.selenium.By;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统登录页面*/
public class LoginPage extends Utils {public static String url = "http://127.0.0.1:9580/sign-in.html";public LoginPage() {super(url);}//通过查看页面元素是否存在来检查页面加载成功与否public void loginPageRight(){//论坛logo图标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 > h2"));}//检查登录功能public void LoginSuc(){//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("xiaoweng");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("0123");//点击登录按钮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("#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"));//通过页面标题来检查是否成功String title = driver.getTitle();assert title.equals("比特论坛");//返回登录页面// driver.navigate().back();//刷新页面// driver.navigate().refresh();}//检查登录失败01--密码错误public void LoginFail01() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("aaa");//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div>h2")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res01.equals("警告");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败02--用户名为空public void LoginFail02() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username"));//输入密码driver.findElement(By.cssSelector("#password")).sendKeys("123456");//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res02 = driver.findElement(By.cssSelector("#signInForm > div.mb-3 > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res02.equals("用户名不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}//检查登录失败03--密码为空public void LoginFail03() throws IOException {//输入用户名driver.findElement(By.cssSelector("#username")).sendKeys("swhdf");//输入密码driver.findElement(By.cssSelector("#password"));//点击登录按钮driver.findElement(By.cssSelector("#submit")).click();//获取当前异常文本String res03 = driver.findElement(By.cssSelector("#signInForm > div.mb-2 > div > div")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert res03.equals("密码不能为空");//通过刷新保证输入框没有文本driver.navigate().refresh();}}

2.5 PageByNoLogin 类 (未登录页面)

未登录状态下,访问类列表页,直接返回登录页面

public class PageByNoLogin extends Utils {public static String listurl = "http://127.0.0.1:9580/index.html";public PageByNoLogin() {super(listurl);}public void ListPageByNoLogin() throws InterruptedException {// driver.get(listurl);//直接返回登录界面Thread.sleep(1000);String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}
}

2.6 ListPage 类 (主页面/列表页)

列表页面是否加载成功,站内信息回复,发布帖子,显示个人帖子,帖子的点赞、编辑、删除以及回复测试,个人中心页面的加载,个人中心的修改,退出等测试。

package tests;import common.Utils;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;import java.io.IOException;
import java.time.Duration;import static org.openqa.selenium.support.ui.ExpectedConditions.textToBe;/*** Created with IntelliJ IDEA.* Description:自动化测试论坛系统列表页面*/
public class ListPage extends Utils{public static String url = "http://127.0.0.1:9580/index.html";public ListPage() {super(url);}//检查页面各个元素是否加载成功public void ListByLoging() throws InterruptedException {//通过页面标题来检查是否成功String title = driver.getTitle();assert title.equals("比特论坛");//通过查看比特论坛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.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-dark > svg")).click();driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div:nth-child(2) > a.nav-link.px-0.hide-theme-light")).click();//输入框测试driver.findElement(By.cssSelector("body > div.page > header.navbar.navbar-expand-md.navbar-light.d-print-none > div > div > div.nav-item.d-none.d-md-flex.me-3 > div > form > div > input"));//信息栏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 > svg"));//个人信息模块driver.findElement(By.cssSelector("#index_nav_avatar")).click();//不同模块点击,点击java模块driver.findElement(By.cssSelector("#topBoardList > li:nth-child(2) > a > span.nav-link-title")).click();//查看java模块第一个帖子是否存在来校验是否切换模块成功driver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div"));}//处理私信成功public void MessageSuc() throws InterruptedException {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 > svg")).click();//等待页面加载//Thread.sleep(4000);//点击消息driver.findElement(By.cssSelector("#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a")).click();//点击回复driver.findElement(By.cssSelector("#btn_index_message_reply")).click();//输入回复信息WebDriverWait foo = new WebDriverWait(driver, Duration.ofSeconds(3));Thread.sleep(2000);foo.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_reply_receive_content"))).sendKeys("越努力越幸运!");//Thread.sleep(3000);// driver.findElement(By.cssSelector("#index_message_reply_receive_content")).sendKeys("越努力越幸运!");//发送driver.findElement(By.cssSelector("#btn_index_send_message_reply")).click();//检验发送成功String sendSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert sendSuc.equals("成功");//关闭信息页面driver.findElement(By.cssSelector("#index_message_offcanvasEnd > div.offcanvas-header > button")).click();}//处理私信失败public void MessageFail() throws InterruptedException, IOException {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 > svg")).click();//等待页面加载//Thread.sleep(4000);//点击消息driver.findElement(By.cssSelector("#index_div_message_list > div:nth-child(1) > div > div.col.text-truncate > a")).click();//点击回复driver.findElement(By.cssSelector("#btn_index_message_reply")).click();//输入回复信息driver.findElement(By.cssSelector("#index_message_reply_receive_content"));//发送Thread.sleep(3000);driver.findElement(By.cssSelector("#btn_index_send_message_reply")).click();//检验发送结果//显示等待WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(3));boolean send = wait.until(ExpectedConditions.textToBe(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2"),"警告"));if(send){getScreenShot(getClass().getName());}else {System.out.println("发送成功");}/*  String sendFail = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert sendFail.equals("警告");
*///显示等待关闭回复框/*WebDriverWait foo = new WebDriverWait(driver, Duration.ofSeconds(10));Thread.sleep(2000);foo.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_reply_modal > div > div > div.modal-header > button"))).click();
*///关闭信息页面WebDriverWait closeWait = new WebDriverWait(driver, Duration.ofSeconds(10));closeWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#index_message_offcanvasEnd > div.offcanvas-header > button"))).click();}//发布帖子成功public void PublishPostSuc() throws IOException {//点击页面发布帖子按钮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")).click();//板块driver.findElement(By.cssSelector("#article_post_borad")).click();driver.findElement(By.cssSelector("#article_post_borad>option:nth-child(1)")).click();//标题driver.findElement(By.cssSelector("#article_post_title")).sendKeys("测试01");//内容driver.findElement(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(20) > a > i")).click();//发布/*      WebDriverWait publishWait = new WebDriverWait(driver, Duration.ofSeconds(50));try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}publishWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#article_post_submit"))).click();*/try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}driver.findElement(By.cssSelector("#article_post_submit")).click();//校验发布成功String pubSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert pubSuc.equals("成功");}//发布帖子失败public void PublishPostFail() throws IOException {//点击页面发布帖子按钮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")).click();//板块driver.findElement(By.cssSelector("#article_post_borad")).click();driver.findElement(By.cssSelector("#article_post_borad>option:nth-child(1)")).click();//标题driver.findElement(By.cssSelector("#article_post_title"));//内容driver.findElement(By.cssSelector("#edit-article > div.editormd-toolbar > div > ul > li:nth-child(20) > a > i")).click();//发布try {Thread.sleep(3000);} catch (InterruptedException e) {throw new RuntimeException(e);}driver.findElement(By.cssSelector("#article_post_submit")).click();/* WebDriverWait publishWait = new WebDriverWait(driver, Duration.ofSeconds(10));try {Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}publishWait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#article_post_submit"))).click();*///校验提示发布失败String pubFail = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();//截图保存测试结果验证警告提示内容是否与预期一致getScreenShot(getClass().getName());assert pubFail.equals("提示");}//显示个人帖子public void ShowPost(){//点击用户driver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击我的帖子driver.findElement(By.cssSelector("#index_user_profile")).click();//查看当前用户昵称是否存在来校验页面是否加载成功driver.findElement(By.cssSelector("#profile_nickname"));//点击当前用户的第一篇帖子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();}//点赞public void LickCount(){ShowPost();driver.findElement(By.cssSelector("#details_btn_like_count")).click();String likeCountSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert likeCountSuc.equals("成功");}//编辑成功public void EditSuc(){ShowPost();//点击当前帖子页面的编辑按钮driver.findElement(By.cssSelector("#details_artile_edit")).click();//清空原标题driver.findElement(By.cssSelector("#edit_article_title")).clear();//修改标题driver.findElement(By.cssSelector("#edit_article_title")).sendKeys("修改标题01");//点击提交driver.findElement(By.cssSelector("#edit_article_submit")).click();String editSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert editSuc.equals("成功");}//编辑失败public void EditFail() throws IOException {ShowPost();//点击当前帖子页面的编辑按钮driver.findElement(By.cssSelector("#details_artile_edit")).click();//清空原标题driver.findElement(By.cssSelector("#edit_article_title")).clear();//点击提交driver.findElement(By.cssSelector("#edit_article_submit")).click();String editSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert editSuc.equals("提示");}//删除成功public void DeleteSuc(){ShowPost();//点击当前帖子页面的删除按钮driver.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();//点击删除driver.findElement(By.cssSelector("#details_delete_modal > div > div > div.modal-footer > div > div > div:nth-child(2)>a")).click();String deleteSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert deleteSuc.equals("成功");}//删除失败public void DeleteFail(){ShowPost();//点击当前帖子页面的删除按钮driver.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();//点击取消driver.findElement(By.cssSelector("#details_delete_modal > div > div > div.modal-footer > div > div > div:nth-child(1) > a")).click();}//回复public void RepleSuc(){ShowPost();//在回复框中输入内容driver.findElement(By.cssSelector("#article_details_reply > div.editormd-toolbar > div > ul > li:nth-child(20) > a")).click();//点击回复按钮driver.findElement(By.cssSelector("#details_btn_article_reply")).click();String replySuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert replySuc.equals("提示");}//回复失败public void RepleFail() throws IOException {ShowPost();//当回复框为空没有内容时直接点击回复按钮driver.findElement(By.cssSelector("#details_btn_article_reply")).click();String replyFail = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert replyFail.equals("提示");}//个人中心public void PersonalCenter(){//点击用户driver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击个人中心driver.findElement(By.cssSelector("#index_user_settings")).click();//通过查看头像是否存在来校验页面是否加载成功driver.findElement(By.cssSelector("#settings_avatar"));}//个人中心修改失败01---修改密码,原密码错误,新密码和确认密码一致public void PersonalCenterModifyFail01() throws IOException {PersonalCenter();//输入原密码driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("0");//输入新密码driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123");//提交修改//driver.findElement(By.cssSelector("#settings_submit_password")).click();driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button")).click();String modifyFail01 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert modifyFail01.equals("警告");//刷新页面driver.navigate().refresh();}//个人中心修改失败02---修改密码,原密码正确,新密码和确认密码不一致public void PersonalCenterModifyFail02() throws IOException {PersonalCenter();//输入原密码driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("0");//输入新密码driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123");//输入确认密码driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123");//提交修改//driver.findElement(By.cssSelector("#settings_submit_password")).click();driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button")).click();String modifyFail02 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert modifyFail02.equals("提示");//刷新页面driver.navigate().refresh();}//个人中心修改失败03---未修改简介内容,确点击修改按钮public void PersonalCenterModifyFail03() throws IOException {driver.findElement(By.cssSelector("#settings_submit_remark")).click();String modifyFail03 = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();getScreenShot(getClass().getName());assert modifyFail03.equals("警告");//刷新页面driver.navigate().refresh();}//个人中心修改成功public void PersonalCenterModifySuc() throws InterruptedException, IOException {PersonalCenter();//清空当前昵称driver.findElement(By.cssSelector("#setting_input_nickname")).clear();//输入要修改的昵称driver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys("阿巴阿巴4");//点击修改driver.findElement(By.cssSelector("#setting_submit_nickname")).click();//提示修改成功String modifyNicknameSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifyNicknameSuc.equals("成功");//清空当前邮箱driver.findElement(By.cssSelector("#setting_input_email")).clear();//输入要修改的邮箱driver.findElement(By.cssSelector("#setting_input_email")).sendKeys("275****82@qq.com");//点击修改driver.findElement(By.cssSelector("#setting_submit_email")).click();//提示修改成功String modifymailSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifymailSuc.equals("成功");//清空当前电话号码driver.findElement(By.cssSelector("#setting_input_phoneNum")).clear();//输入要修改的电话号码driver.findElement(By.cssSelector("#setting_input_phoneNum")).sendKeys("151*****123");//点击修改driver.findElement(By.cssSelector("#setting_submit_phoneNum")).click();//提示修改成功String modifTelySuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifTelySuc.equals("成功");//个人简介driver.findElement(By.cssSelector("#settings_textarea_remark")).clear();driver.findElement(By.cssSelector("#settings_textarea_remark")).sendKeys("东海皇帝");driver.findElement(By.cssSelector("#settings_submit_remark")).click();//提示修改成功String modifTextSuc = driver.findElement(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")).getText();assert modifTextSuc.equals("成功");//输入原密码driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys("0123");//输入新密码driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys("123");//输入新密码driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys("123");//提交修改//driver.findElement(By.cssSelector("#settings_submit_password")).click();driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div > div.col.d-flex.flex-column > div > div:nth-child(14) > div > div > form > div.form-footer>button")).click();getScreenShot(getClass().getName());//注册成功返回登录页面Thread.sleep(1000);String title = driver.getTitle();assert title.equals("比特论坛 - 用户登录");}//退出public void Exit(){//点击用户driver.findElement(By.cssSelector("#index_nav_avatar")).click();//点击退出driver.findElement(By.cssSelector("#index_user_logout#index_user_logout")).click();}}

2.7 RunTest 类(测试运行)

import common.Utils;
import tests.ListPage;
import tests.LoginPage;
import tests.PageByNoLogin;
import tests.RegisterPage;import java.io.IOException;/*** Created with IntelliJ IDEA.* Description:论坛系统自动化测试* Author: WJW* Date: 2024-10-16* Time: 19:16*/
public class RunTests {public static void main(String[] args) throws IOException, InterruptedException {//未登录页面测试PageByNoLogin pageByNoLogin = new PageByNoLogin();pageByNoLogin.ListPageByNoLogin();RegisterPage register = new RegisterPage();
//        //测试注册页面是否加载成功register.RegisterPageRight();
//        //注册成功register.RegisterSuc();//注册失败register.RegisterFai01();register.RegisterFai02();register.RegisterFai03();register.RegisterFai04();register.RegisterFai05();LoginPage login = new LoginPage();//测试登录页面是否加载成功login.loginPageRight();//登录失败login.LoginFail01();login.LoginFail02();login.LoginFail03();// 登录成功login.LoginSuc();ListPage list = new ListPage();//测试列表页面是否加载成功list.ListByLoging();//测试站内信息回复成功list.MessageSuc();//测试站内信息回复失败list.MessageFail();//成功发布帖子list.PublishPostSuc();//发布帖子失败list.PublishPostFail();//显示个人帖子list.ShowPost();// 点赞list.LickCount();//编辑成功list.EditSuc();//编辑失败list.EditFail();//删除成功list.DeleteSuc();//删除失败list.DeleteFail();//回复成功list.RepleSuc();//回复失败list.RepleFail();//个人中心list.PersonalCenter();//个人中心修改失败list.PersonalCenterModifyFail01();list.PersonalCenterModifyFail02();list.PersonalCenterModifyFail03();//个人中心修改成功list.PersonalCenterModifySuc();//退出list.Exit();//释放driver对象Utils.driver.quit();}
}

3. 性能测试

性能测试码云链接:FourmPerformanceTest

使用 jmeter 进行简单性能测试:针对登录、编写并发布帖子以及删除帖子、退出等功能进行简单的性能测试。然后在实现的过程中,添加梯度压测线程组,来实现用户的并发操作。

3.1 HTTP请求默认值

论坛中涉及到的接口协议、IP、端口号全都⼀样,可以单独抽取出来存放在默认值中,其他接口就可以省略不写协议、IP、端口号口。
在这里插入图片描述

在这里插入图片描述

3.2 CSV数据文件设置

以登陆接口为例,当我们执⾏登陆接口的性能测试时,手动配置了用户名和密码为固定的username和password,然而实际使⽤中不可能只有⼀个用户登录陆,为了模拟更真实的登录环境,我们需要提供更多的用户username和password来实现登录操作
添加⽅式:线程组⸺⸺配置元件⸺⸺CSV数据⽂件设置
在这里插入图片描述
操作步骤:
1)CSV数据文件设置

  • 文件名:填写csv文件的路径。建议使用绝对路径。
  • 文件编码:UTF-8
  • 变量名称:从csv数据⽂件中读起的数据需要保存到的变量名。有多个变量时⽤逗号分隔
  • 是否忽略首行:是否从csv数据文件第⼀行开始读取。
  • 分隔符:要求与csv数据文件中多列的分隔符⼀致
  • 遇到文件结束符再次循环:若选择为True当数据不够的时候会从头取。若选择False,则需要勾选下面的配置,遇到⽂件结束符停止线程,这⾥如果不勾选,请求将会报错。

在这里插入图片描述
2)编写loginTest.csv⽂件:
在这里插入图片描述
3)修改登陆接口及其他涉及到username和password获取的参数。修改完该配置后,登陆接口发起请求时将从csv文件中获取配置好的username和password参数,获取顺序为从上往下依次获取
在这里插入图片描述
4)修改线程组中线程数,使得每次取到的username和password都不⼀样
在这里插入图片描述
5)运行结果
在这里插入图片描述

3.3 梯度压测

  • 添加梯度压测线程组
    在这里插入图片描述

对各个接口进行压力测试,设当前线程有100(小编的电脑上万的跑不起来,这里就以100为例)

  • This group will start:启动多少个线程,同线程组中的线程数
  • First,wait for:等待多少秒才开始压测,一般默认为0
  • Then start:一开始有多少个线程数,一般默认为0
  • Next,add:下一次增加多少个线程数
  • threads every:当前运⾏多⻓时间后再次启动线程,即每⼀次线程启动完成之后的的持续时间
  • using ramp-up:启动线程的时间;若设置为1秒,表示每次启动线程都持续1秒
  • thenhold loadfor:线程全部启动完之后持续运行多长时间
  • finally,stop/threadsevery:多长时间释放多少个线程;若设置为20个和1秒,表示持续负载结束之后每1秒钟释放20个线程

在这里插入图片描述

  • 聚合报告
    从聚合报告可以看到性能测试过程中整体的数据变化,没有发现异常
    在这里插入图片描述

  • Response Times Over Time主要用于监听整个事务运⾏期间的响应时间,观察并分析响应时间的实时平均值以及整体响应时间的走向。通过这⼀监听器,能够更直观地了解系统在不同时间点的响应性能。
    在这里插入图片描述
    Response Times Over Time的图形展示中,横坐标通常代表运行时间,而纵坐标则代表响应时间(单位是毫秒)。

  • 从性能测试报告中可以清晰的看到,所有接口的测试都通过!
    在这里插入图片描述

本章到这里就结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话请给个三连支持一下吧!
Fighting!!!✊

相关文章:

【项目】论坛系统测试

文章目录 一、项目介绍二、测试环境三、测试用例3.1 论坛系统功能测试用例3.2 论坛系统非功能测试用例 四、测试计划1. 手工测试1.1 注册页面1.2 登陆页面1.3 主页面&#xff08;列表页&#xff09; 2. 自动化测试2.1 添加对应的依赖2.2 Utils类&#xff08;公有类&#xff09;…...

XJ02、消费金融|消费金融业务模式中的主要主体

根据所持有牌照类型的不同&#xff0c;消费金融服务供给方主要分为商业银行、汽车金融公司、消费金融公司和小贷公司&#xff0c;不同类型机构定位不同、提供消费金融服务与产品类型也各不相同。此外&#xff0c;互联网金融平台也成为中国消费金融业务最重要的参与方之一&#…...

基于神经网络的农业病虫害损失预测

【摘 要】鉴于农业病虫害经济损失的预测具有较强的复杂性和非线性特性&#xff0c;设计了一种新型的GRNN预测模型&#xff0c;对农业病虫害经济损失进行预测。该模型基于人工神经网络捕捉非线性变化独特的优越性&#xff0c;在神经网络技术和江苏省气象局提供的数据的基础上&am…...

【DSP】TI 微控制器和处理器的IDE安装CCSTUDIO

【DSP】TI 微控制器和处理器的IDE安装CCSTUDIO 1.背景2.下载IDE3.安装IDE1.背景 TI:Texas instruments即德州仪器公司。 https://www.ti.com.cn/CCSTUDIO即Code Composer Studio。 Code Composer Studio 是适用于 TI 微控制器和处理器的集成开发环境 (IDE)。 它包含一整套用于…...

Web应用框架-Django应用基础

1. 认识Django Django是一个用Python编写的开源高级Web框架&#xff0c; 旨在快速开发可维护和可扩展的Web应用程序。 使用Django框架的开发步骤&#xff1a; 1.选择合适的版本 2.安装及配置 3.生成项目结构 4.内容开发 5.迭代、上线、维护 Django官网&#xff1a; Djang…...

qt QMainWindow详解

一、概述 QMainWindow继承自QWidget&#xff0c;并提供了一个预定义的布局&#xff0c;将窗口分成了菜单栏、工具栏、状态栏和中央部件区域。这些区域共同构成了一个功能丰富的主窗口&#xff0c;使得应用程序的开发更加简单和高效。 二、QMainWindow的常用组件及功能 菜单栏&…...

第二单元历年真题整理

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 参考答案 1. A 2. A 3. A 4. D 5. D 6. D 解析&#xff1a; 栈和队列是两个不一样的结构&#xff0c;不能放在一起表示 7. B 8. C 解析&#xff1a; S --> A0 | B1 --> (S1 | 1) 0 | (S0 | 0)1 --> S10 | 10 | S…...

Ubuntu下载protobuf

1 安装依赖库 sudo apt-get install autoconf automake libtool curl make g unzip -y2 下载protobuf ProtoBuf 下载地址:https://github.com/protocolbuffers/protobuf/releases 如果要在 C 下使⽤ ProtoBuf&#xff0c;可以选择cpp.zip 其他语言选择对应的链接即可 希望支持…...

【算法优化】混合策略改进的蝴蝶优化算法

摘要 蝴蝶优化算法 (Butterfly Optimization Algorithm, BOA) 是一种新兴的智能优化算法&#xff0c;其灵感来自蝴蝶的觅食行为。本文基于经典BOA&#xff0c;通过引入混合策略进行改进&#xff0c;从而提高其在全局寻优和局部搜索中的性能。实验结果表明&#xff0c;改进的蝴…...

什么是标准差?详解

文章目录 一、什么是标准差&#xff1f;二、公式三、举个例子&#x1f330;参考 一、什么是标准差&#xff1f; 在统计学中&#xff0c;标准差&#xff08;Standard Deviation&#xff09;是用于衡量变量值围绕其平均值变化程度的指标。低标准差表示这些值通常接近平均值&…...

C++20中头文件syncstream的使用

<syncstream>是C20中新增加的头文件&#xff0c;提供了对同步输出流的支持&#xff0c;即在多个线程中可安全地进行输出操作&#xff0c;此头文件是Input/Output库的一部分。包括&#xff1a; 1.std::basic_syncbuf&#xff1a;是std::basic_streambuf的包装器(wrapper)&…...

判断特定时间点开仓的函数(编程技巧)

如何使用最新的MQL4语言创建并应用一个判断当前是否可以开启或增加交易仓位的函数。通过详细讲解函数的代码实现、核心功能及其在实际交易策略中的调用方法。 函数代码 以下是一个用MQL4编写的函数&#xff0c;用于检测在特定时间点是否可以开仓或增仓。 extern int MagicNumb…...

如何新建一个React Native的项目

要新建一个 React Native 项目&#xff0c;你可以使用 React Native 官方推荐的工具 React Native CLI 或者 Expo。两者的区别在于&#xff1a;React Native CLI 提供更多对原生代码的访问权限&#xff0c;适合构建复杂的应用&#xff1b;而 Expo 是一个开发工具链&#xff0c;…...

学习--图像信噪比

目录 图像信噪比 图像信噪比 图像信噪比的计算公式&#xff1a; 其中&#xff0c; M M M和 N N N分别表示图像长度和宽度上的像素数。 f ( i , j ) f(i,j) f(i,j) 和 g ( i , j ) g(i,j) g(i,j)分别是原始图像和去噪后的图像在点 ( i , j ) (i,j) (i,j)处的像素值。 信噪…...

【2024CANN训练营第二季】使用华为云体验AscendC_Sample仓算子运行

环境介绍 NPU&#xff1a;Ascend910B2 环境准备 创建Notebook 华为云选择&#xff1a;【控制台】-【ModelArts】 ModelArts主页选择【开发生产】-【开发空间】-【Notebook】 页面右上角选择【创建Notebook】 选择资源 主要参数 规格&#xff1a;Ascend: 1*ascend-snt…...

使用 NumPy 和 Matplotlib 实现交互式数据可视化

使用 NumPy 和 Matplotlib 实现交互式数据可视化 在数据分析中&#xff0c;交互式可视化可以更好地帮助我们探索和理解数据。虽然 Matplotlib 是静态绘图库&#xff0c;但结合一些技巧和 Matplotlib 的交互功能&#xff08;widgets、event handlers&#xff09;&#xff0c;我…...

TCP 攻击为何在 DDoS 攻击中如此常见

分布式拒绝服务攻击&#xff08;Distributed Denial of Service, DDoS&#xff09;是一种常见的网络攻击手段&#xff0c;通过大量请求使目标服务器过载&#xff0c;导致合法用户无法访问服务。在众多 DDoS 攻击类型中&#xff0c;TCP 攻击尤为常见。本文将探讨 TCP 攻击在 DDo…...

未来汽车驾驶还会有趣吗?车辆动力学系统简史

未来汽车驾驶还会有趣吗&#xff1f;车辆动力学系统简史 本篇文章来源&#xff1a;Schmidt, F., Knig, L. (2020). Will driving still be fun in the future? Vehicle dynamics systems through the ages. In: Pfeffer, P. (eds) 10th International Munich Chassis Symposiu…...

LCD手机屏幕高精度贴合

LCD手机屏幕贴合&#xff0c;作为智能手机生产线上至关重要的一环&#xff0c;其质量直接关乎用户体验与产品竞争力。这一工艺不仅要求屏幕组件间的无缝对接&#xff0c;达到极致的视觉与触觉效果&#xff0c;还需确保在整个生产过程中&#xff0c;从材料准备到最终成品&#x…...

15_卸载操作

在之前我们就提到&#xff0c;首次渲染之后&#xff0c;后续如果再调用 render 函数时&#xff0c;传递的 vnode 为 null 则表示是卸载。 当时我们是直接通过执行 container.innerHTML ‘’ 来实现的&#xff0c;但是这样做会有以下几个问题&#xff0c;如下&#xff1a; 容…...

ONLYOFFICE 文档8.2版本已发布:PDF 协作编辑、改进界面、性能优化等更新

ONLYOFFICE 在线编辑器最新版本已经发布&#xff0c;其中包含30多个新功能和500多个错误修复。阅读本文了解所有更新。 关于 ONLYOFFICE 文档 ONLYOFFICE 是一个开源项目&#xff0c;专注于高级和安全的文档处理。坐拥全球超过 1500 万用户&#xff0c;ONLYOFFICE 是在线办公领…...

redis的string是怎么实现的

Redis 的 String 类型是最基本的数据类型&#xff0c;底层通过多种方式实现&#xff0c;能够存储字符、整数、浮点数等各种形式的值。String 数据结构的实现基于 Redis 的简单动态字符串&#xff08;SDS&#xff09;&#xff0c;同时在处理不同的数据类型时也进行了优化。 1. …...

基于STM32设计的智能婴儿床(华为云IOT)(244)

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成【4】ESP8266工作模式配置1.2 设计思路【1】整体设计思路【2】整体构架【3】上位机开发思路1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要1.4 开发工具的选择【1…...

html+css+js实现Notification 通知

实现效果&#xff1a; 代码实现&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Notif…...

【Linux】拆分详解 - 常见指令和权限理解

文章目录 前言一、常用指令1. 基本查看与路径跳转1.1文件与目录1.2 ls 指令&#xff08;显示文件&#xff09;1.3 pwd &#xff08;查看当前目录&#xff09;1.4 clear &#xff08;清屏&#xff09;1.5 whoami &#xff08;查看用户名&#xff09;1.6 cd&#xff08;跳转路径&…...

UniHttp 框架,请求http接口

项目案例下载地址: https://download.csdn.net/download/jinhuding/89902024 1.快速开始 2.1引入依赖 <dependency><groupId>io.github.burukeyou</groupId><artifactId>uniapi-http...

C++20中头文件ranges的使用

<ranges>是C20中新增加的头文件&#xff0c;提供了一组与范围(ranges)相关的功能&#xff0c;此头文件是ranges库的一部分。包括&#xff1a; 1.concepts: (1).std::ranges::range:指定类型为range&#xff0c;即它提供开始迭代器和结束标记(it provides a begin iterato…...

设计一个html+css+js的注册页,对于注册信息进行合法性检测

综合使用HTML、JavaScript和CSS进行注册页面设计&#xff0c;实现以下若干功能&#xff1a; 注意整个页面的色调和美观使用FramesetTable布局&#xff08;div也可&#xff09;对用户ID和用户名、口令不符合条件及时判断对口令不一致进行及时判断&#xff08;34的及时判断&#…...

语音识别——使用Vosk进行语音识别

文章目录 前言一、Vosk模型1.准备好所需要的语音包2.下载使用 二、使用示例1.文件读取示例2.结合麦克风演示 总结 前言 如何编译Vosk请参照之前的文章&#xff0c;ubuntu编译kaldi和vosk Vosk是语音识别开源框架&#xff0c;支持二十种语言 - 中文&#xff0c;英语&#xff0…...

element ui中el-image组件查看图片的坑

比如说上传组件使用el-image-viewer组件去看,如果用错了,你会发现,你每次只能看一张图片 <template><div><el-upload action="#" list-type="picture-card" :auto-upload="false" :file-list="fileList"@change=&qu…...

网站不加www/给公司做网站要多少钱

伺服驱动器的工作原理及伺服驱动器的常见接线方法&#xff1a; 伺服驱动器在控制信号的作用下驱动执行电机&#xff0c;因此驱动器是否能正常工作直接影响设备的整体性能。在伺服控制系统中&#xff0c;伺服驱动器相当于大脑&#xff0c;执行电机相当于手脚。而伺服驱动器在伺服…...

维护一个网站要多少钱/安新seo优化排名网站

php修改文件内容的方法&#xff1a;首先通过file_put_contents函数写入文件&#xff1b;然后使fwrite配合fopen进行写入并修改的操作&#xff1b;最后通过file_exists等函数检测文件属性即可。file_put_contents写入文件我们先来学习第一种写入文件的方式&#xff1a;int file_…...

网站开发合同范本/外贸网络营销

【题目描述】&#xff1a; 幼儿园里有N个小朋友,1xhgww老师现在想要给这些小朋友们分配糖果&#xff0c;要求每个小朋友都要分到糖果。但是小朋友们也有嫉妒心&#xff0c;总是会提出些要求&#xff0c;比如小明不希望小红分到的糖果比他的多&#xff0c;于是在分配糖果的时候l…...

网站建设战略伙伴/手机百度引擎搜索入口

安装完kvm虚拟机后&#xff0c;对虚拟机做快照&#xff08;关闭虚拟机&#xff09;&#xff1a;kvm快照&#xff0c;分两种&#xff1a;1种lvm快照&#xff0c;如果分区是lvm&#xff0c;可以利用lvm进行kvm的快照备份2种由于raw格式不支持镜像&#xff0c;所以需要将格式转换为…...

wordpress获取不同分类文章/电商seo是什么

绵绵的细雨挥洒在川蜀大地&#xff0c;到处都弥漫着泥土的清新和芳香。一大清早我就跑到了板房区的管委会&#xff0c;去赶前往北川任家坪的祭奠专用车。等我到了停车场后一看&#xff0c;好多人已经在那里排队。所以我就跑到了马路边去赶过往的班车。 一路上&#xff0c;我轻轻…...

南水北调中线干线工程建设管理局网站/新闻软文发布平台

(1)Constructing Objects at Run Time in SilverlightSilverlight的内容在你的页面上就像一个对象层次在树的结构中样.这是单个的.一个在这个结构中最顶上的对象是root object,也是Silverlight plug-in的Source指定相应的XAML中的root.这 个root对象通常是一个Canvas对象,因为C…...