【项目】论坛系统测试

文章目录
- 一、项目介绍
- 二、测试环境
- 三、测试用例
- 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 添加对应的依赖
- 先添加对应的依赖
<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 主页面(列表页) 2. 自动化测试2.1 添加对应的依赖2.2 Utils类(公有类)…...
XJ02、消费金融|消费金融业务模式中的主要主体
根据所持有牌照类型的不同,消费金融服务供给方主要分为商业银行、汽车金融公司、消费金融公司和小贷公司,不同类型机构定位不同、提供消费金融服务与产品类型也各不相同。此外,互联网金融平台也成为中国消费金融业务最重要的参与方之一&#…...
基于神经网络的农业病虫害损失预测
【摘 要】鉴于农业病虫害经济损失的预测具有较强的复杂性和非线性特性,设计了一种新型的GRNN预测模型,对农业病虫害经济损失进行预测。该模型基于人工神经网络捕捉非线性变化独特的优越性,在神经网络技术和江苏省气象局提供的数据的基础上&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框架, 旨在快速开发可维护和可扩展的Web应用程序。 使用Django框架的开发步骤: 1.选择合适的版本 2.安装及配置 3.生成项目结构 4.内容开发 5.迭代、上线、维护 Django官网: Djang…...
qt QMainWindow详解
一、概述 QMainWindow继承自QWidget,并提供了一个预定义的布局,将窗口分成了菜单栏、工具栏、状态栏和中央部件区域。这些区域共同构成了一个功能丰富的主窗口,使得应用程序的开发更加简单和高效。 二、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 解析: 栈和队列是两个不一样的结构,不能放在一起表示 7. B 8. C 解析: 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,可以选择cpp.zip 其他语言选择对应的链接即可 希望支持…...
【算法优化】混合策略改进的蝴蝶优化算法
摘要 蝴蝶优化算法 (Butterfly Optimization Algorithm, BOA) 是一种新兴的智能优化算法,其灵感来自蝴蝶的觅食行为。本文基于经典BOA,通过引入混合策略进行改进,从而提高其在全局寻优和局部搜索中的性能。实验结果表明,改进的蝴…...
什么是标准差?详解
文章目录 一、什么是标准差?二、公式三、举个例子🌰参考 一、什么是标准差? 在统计学中,标准差(Standard Deviation)是用于衡量变量值围绕其平均值变化程度的指标。低标准差表示这些值通常接近平均值&…...
C++20中头文件syncstream的使用
<syncstream>是C20中新增加的头文件,提供了对同步输出流的支持,即在多个线程中可安全地进行输出操作,此头文件是Input/Output库的一部分。包括: 1.std::basic_syncbuf:是std::basic_streambuf的包装器(wrapper)&…...
判断特定时间点开仓的函数(编程技巧)
如何使用最新的MQL4语言创建并应用一个判断当前是否可以开启或增加交易仓位的函数。通过详细讲解函数的代码实现、核心功能及其在实际交易策略中的调用方法。 函数代码 以下是一个用MQL4编写的函数,用于检测在特定时间点是否可以开仓或增仓。 extern int MagicNumb…...
如何新建一个React Native的项目
要新建一个 React Native 项目,你可以使用 React Native 官方推荐的工具 React Native CLI 或者 Expo。两者的区别在于:React Native CLI 提供更多对原生代码的访问权限,适合构建复杂的应用;而 Expo 是一个开发工具链,…...
学习--图像信噪比
目录 图像信噪比 图像信噪比 图像信噪比的计算公式: 其中, 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:Ascend910B2 环境准备 创建Notebook 华为云选择:【控制台】-【ModelArts】 ModelArts主页选择【开发生产】-【开发空间】-【Notebook】 页面右上角选择【创建Notebook】 选择资源 主要参数 规格:Ascend: 1*ascend-snt…...
使用 NumPy 和 Matplotlib 实现交互式数据可视化
使用 NumPy 和 Matplotlib 实现交互式数据可视化 在数据分析中,交互式可视化可以更好地帮助我们探索和理解数据。虽然 Matplotlib 是静态绘图库,但结合一些技巧和 Matplotlib 的交互功能(widgets、event handlers),我…...
TCP 攻击为何在 DDoS 攻击中如此常见
分布式拒绝服务攻击(Distributed Denial of Service, DDoS)是一种常见的网络攻击手段,通过大量请求使目标服务器过载,导致合法用户无法访问服务。在众多 DDoS 攻击类型中,TCP 攻击尤为常见。本文将探讨 TCP 攻击在 DDo…...
未来汽车驾驶还会有趣吗?车辆动力学系统简史
未来汽车驾驶还会有趣吗?车辆动力学系统简史 本篇文章来源: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手机屏幕贴合,作为智能手机生产线上至关重要的一环,其质量直接关乎用户体验与产品竞争力。这一工艺不仅要求屏幕组件间的无缝对接,达到极致的视觉与触觉效果,还需确保在整个生产过程中,从材料准备到最终成品&#x…...
15_卸载操作
在之前我们就提到,首次渲染之后,后续如果再调用 render 函数时,传递的 vnode 为 null 则表示是卸载。 当时我们是直接通过执行 container.innerHTML ‘’ 来实现的,但是这样做会有以下几个问题,如下: 容…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...
STM32标准库-ADC数模转换器
文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”:输入模块(GPIO、温度、V_REFINT)1.4.2 信号 “调度站”:多路开关1.4.3 信号 “加工厂”:ADC 转换器(规则组 注入…...
结构化文件管理实战:实现目录自动创建与归类
手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题,进而引发后续程序异常。使用工具进行标准化操作,能有效降低出错概率。 需要快速整理大量文件的技术用户而言,这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB,…...













