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

校园论坛系统Selenium自动化测试

本文为自动化测试

 本项目自动化测试代码链接(仅供参考):  自动化测试代码

功能测试文章链接: 校园论坛系统自动化测试报告-CSDN博客

 🌈自动化测试

思维导图

根据思维导图, 我们选取几个主要的功能进行自动化测试

编写代码

思路: 

  1. 根据脑图进行测试用例的编写:每个页面一个测试类,然后再各个测试类中进行测试用例的编写
  2. 注意公共属性需要单独放一个类,方便进行代码复用
  3. 使用测试套件便于运行以及修改
  4. 创建启动以及现场截图就是会频繁进行复用,所以单独创建一个类进行存储
  5. 注意添加隐式等待,为了确保页面正确加载显示

💨准备工作

引入相关依赖

        <!--  屏幕截图  --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><!--   驱动管理     --><dependency><groupId>io.github.bonigarcia</groupId><artifactId>webdrivermanager</artifactId><version>5.8.0</version></dependency><!--    selenium    --><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.0.0</version></dependency>

⭐创建常用工具类(AutoTestUtil)

工具类主要包含两个方法: 

1. 创建驱动对象: 测试过程会频繁创建和销毁, 可以封装成一个方法, 方便使用
2. 屏幕截图: 测试过程可能会出现问题, 可以使用屏幕截图保存问题界面, 便于后面分析

    要求: 图片文件名要做到: 见文知意, 方便问题追溯, 具体到 年月日时分秒, 以及方法名

3. 获取当前方法名: 通过跟踪堆栈信息获取调用者的方法名

下面是参考代码: 

public class AutoTestUtil {public static ChromeDriver driver = null;// 创建谷歌驱动对象public static ChromeDriver createDriverUtil() {// 驱动打开谷歌浏览器WebDriverManager.chromedriver().setup();// 配置安全策略ChromeOptions options = new ChromeOptions();options.addArguments("--remote-allow-origins=*");// 无头模式, 可以后台执行, 观察效果就关闭
//        options.addArguments("--headless=new");// 将配置添加到浏览器对象中if (driver == null) {driver = new ChromeDriver(options);}// 添加 隐式等待 确保页面元素渲染出来driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));return driver;}// 屏幕截图: 文件名带有类名和方法名public static void getScreenshotAs(String classMethodName) throws IOException {// 1. 用一个单独文件夹存放截图文件// 2. 出问题能够快速定位到(方便查找, 见名知意)SimpleDateFormat ymd = new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat hms = new SimpleDateFormat("HH_mm_ss_SS");  // HH:mm:ss 文件名字不能带有 :, 所以使用 _String currentYMD = ymd.format(System.currentTimeMillis());String currentHMS = hms.format(System.currentTimeMillis());// 截图存储的路径String filePath = "./src/test/image/" + currentYMD + "/" + classMethodName + "_" +currentHMS + ".png";// 截图File screenshotAs = ( (TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);File destFile = new File(filePath);// 保存到指定目录FileUtils.copyFile(screenshotAs, destFile);}// 获取调用者方法名public static String currentMethodName() {// 通过跟踪堆栈信息获取方法名StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();// 索引选择规则:// stackTrace[0] -> getStackTrace() 方法本身// stackTrace[1] -> 当前方法(currentMethodName)// stackTrace[2] -> 调用者方法(比如main)return stackTrace[2].getMethodName();}}

每个页面的测试方法都使用一个类存放

⭐测试注册界面(ForumRegisterTest)

① 创建驱动,并打开注册页面
② 测试页面是否正常打开
③ 测试正常注册:多参数测试
④ 测试异常注册:密码和确认密码不一致的情况(此处不测null)
⑤ 注意测试方法的执行顺序,使用Order注解指定执行顺序

验证注册成功的情况

场景1:注册用户名在数据库不存在,昵称,两次密码一致,注册成功,跳转到登录界面

☑️预期结果: 注册成功, 跳转到登录界面

代码如下: 

    @Order(1)@ParameterizedTest@CsvSource({"Shylock, 夏洛克, 123456, 123456"})void register(String username, String nickname, String password, String passwordRepeat) throws InterruptedException, IOException {driver.get("http://127.0.0.1:11451/sign-up.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#nickname")).sendKeys(nickname);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#passwordRepeat")).sendKeys(passwordRepeat);// 点击同意用户协议driver.findElement(By.cssSelector("#policy")).click();// 点击注册driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

✅实际结果: 与预期结果相符

❌验证注册失败的情况

场景2:注册用户名在数据库存在,昵称,两次密码一致,注册失败

☑️预期结果: 提示当前用户已注册

代码如下: 测试代码和注册成功的代码一样
✅实际结果: 与预期结果相符

⭐测试登录界面(ForumLoginTest)

测试点:

① 创建驱动,并打开页面
② 测试页面是否正常打开
③ 测试正常登录:多参数测试
④ 测试异常登录:用户名/密码错误的情况(此处不测null)
⑤ 注意测试的顺序,使用Order注解指定,否则可能会因为执行顺序不对导致测试失败
⑥ 注意清空内容后才能再次输入用户名以及密码

登录成功测试

场景1:测试用户名正确,密码正确,登录成功(多个用户)

☑️预期效果: 两个用户都登录成功

代码如下: 

    @Order(1)@ParameterizedTest@CsvSource({"zhangsan, 123456", "2, 2"})void login(String username, String password) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();// 截图, 查看是否登录成功, 等待一秒, 防止页面没加载出来就截图了Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

✅实际效果: 与预期效果相符

❌登录失败测试

场景2:测试用户名正确,密码错误,登录失败

             测试用户名错误,密码错误,登录失败

☑️预期结果: 提示用户名或者密码错误和用户不存在

代码如下: 

    @Order(2)@ParameterizedTest@CsvSource({"zhangsan, 12345", "error1, error2"})void noLogin(String username, String password) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

✅实际结果: 与预期结果相符

⭐测试论坛主页(ForumIndexTest)

① 测试论坛主页是否可以正常打开
② 测试未登录的直接链接是否会跳转到登录页面
③ 查看“首页”元素是否存在,查看是否含有“发布帖子”按钮
④ 同样注意执行顺序

❌未登录状态下测试

场景1:未登录状态下进入论坛主页,直接跳转回登录界面

☑️预期结果: 直接跳转回登录界面

✅实际结果: 与预期结果相符

代码如下: 

    // 未登录状态访问论坛主页@Order(1)@Testvoid noLoginVisitIndex() {driver.get("http://127.0.0.1:11451/index.html");}

✅登录状态下测试

场景2:登录后进入博客列表页,查看“首页”元素是否存在,查看是否含有“发布帖子”按钮

☑️预期结果: 在论坛主页可以找到对应的选择器或XPath, 点击发布贴子会跳转到贴子创作页

代码如下: 

    @Order(2)@ParameterizedTest@CsvSource({"zhangsan, 123456"})void forumIndexByLogin (String username, String password) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();String str1 = driver.findElement(By.cssSelector("#nav_board_index > a > span.nav-link-title")).getText();// 断言 "首页" 元素存在Assertions.assertEquals("首页", str1);// 发布按钮, 点击会跳转到贴子发布页面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();// 截图, 查看是否跳转成功, 等待一秒, 防止页面没加载出来就截图了Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

✅实际结果: 断言通过, 也找到了发布按钮

⭐测试发布帖子(writePostTest)

测试要点: 

① 测试发布页是否可以正确打开
② 测试是否可以正常发布:元素齐全 or 部分元素
③ 测试“发布”按钮是否可以正常使用
④ 执行顺序

未登录状态下测试

场景1:未登录状态下发布帖子,直接跳转回登录界面

和前面类似, 但是测试用例不能少, 由于篇幅限制就不多演示了

☑️预期结果: 直接跳转回登录界面

✅实际结果: 与预期结果相符

登录后测试

场景2:登录后,输入帖子标题,不输入帖子内容,点击发布按钮,给出提示信息

☑️预期结果: 提示: 请输入贴子内容

代码如下: 

    @Order(2)@ParameterizedTest@CsvSource({"zhangsan, 123456"})void writeActicleFailByLogin(String username, String password) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();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();String str1 = driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div.card-body > div:nth-child(1) > label > strong")).getText();// 断言判断是否处于发布贴子的页面Assertions.assertEquals("版块", str1);// 输入标题driver.findElement(By.cssSelector("#article_post_title")).sendKeys("标题");// 不输入内容, 直接发布, 查看是否提示: 请输入文章内容// 由于发布按钮需要向下滚动才能看到, 显示等待发布按钮加载WebElement element = driver.findElement(By.cssSelector("#article_post_submit"));driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));// 将指定元素滑动到页面顶部((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", element);// 确保滚动成功Thread.sleep(1000);element.click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

✅实际结果: 与预期结果相符

场景三: 登录后,输入帖子标题,输入帖子内容,点击发布按钮,发布成功

☑️预期结果: 跳转回论坛主页, 且在上方显示贴子信息

✅实际结果: 与预期结果相符

代码直接在前面的测试的方法上加上输入文本的操作即可

注意: editor编辑器不能通过选择选择到, 可以使用 键盘Tab 进行选择, 然后sendKeys即可

⭐测试贴子详情页(ActicleDetailTest)

① 测试详情页的正确打开
② 测试作者和用户权限是否一致

③ 功能是否正常
④ 执行顺序
⑤ 一定要注意导航回到列表页的操作

未登录状态下

场景1:未登录状态下,进入贴子详情页,直接跳转回登录界面

☑️预期结果: 直接跳转回登录界面

✅实际结果: 与预期结果相符

和前面类似, 但是测试用例不能少, 由于篇幅限制就不多演示了

登录状态下

页面基础元素: 贴子标题、贴子内容、贴子作者、点赞按钮

特殊元素: 如果是作者, 会多显示 编辑按钮 和 删除按钮

场景1:登录后, 进入贴子详情界面, 且用户为贴子作者

☑️预期结果: 多显示 编辑按钮 和 删除按钮

✅实际结果: 与预期结果相符

场景2:登录后, 进入贴子详情界面, 用户不为贴子作者

☑️预期结果: 只显示 贴子标题、贴子内容、贴子作者、点赞按钮

✅实际结果: 与预期结果相符

两个用例一块测试了

场景1执行后的页面

场景2执行后的页面

测试代码如下: 

    @Order(2)@ParameterizedTest@CsvSource({"2, 2", "zhangsan, 123456"})void acticleDetailByLogin(String username, String password) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();// 断言进入到首页Assertions.assertEquals(driver.findElement(By.cssSelector("#article_list_board_title")).getText(), "首页");// 进入到第一个贴子,如果页面上存在多个匹配相同定位条件的元素, 会默认返回第一个WebElement element = driver.findElement(By.cssSelector("#artical-items-body > div:nth-child(1) > div > div.col > div.text-truncate > a > strong"));element.click();// 断言进入了文章详情页面element = driver.findElement(By.cssSelector("#bit-forum-content > div.page-body > div > div > div:nth-child(2) > h3"));Assertions.assertEquals(element.getText(), "最新回复");Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

⭐测试删除贴子

❌未登录测试

场景1: 未登录状态下,点击删除

☑️预期结果: 直接跳转回登录界面

✅实际结果: 与预期结果相符

和前面类似, 但是测试用例不能少, 由于篇幅限制就不多演示了

登录状态下测试

场景1:登录后,进入帖子详情页,点击删除按钮,删除帖子成功,成功跳转回帖子列表页面

前提是当前登录用户为贴子作者

☑️预期结果: 提示删除成功

✅实际结果: 与预期结果相符

测试代码如下: 在上一个测试用例后面加上这串代码即可

        element = 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 > span"));// 断言当前用户是作者Assertions.assertEquals(element.getText(), "删除");element.click();driver.findElement(By.cssSelector("#details_artile_delete")).click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());

⭐测试所有帖子页面

❌未登录测试

场景1: 未登录状态下,点击我的帖子

☑️预期结果: 直接跳转回登录界面

✅实际结果: 与预期结果相符

和前面类似, 但是测试用例不能少, 由于篇幅限制就不多演示了

✅登录状态下测试

场景2:登录状态下, 点击我的帖子

☑️预期结果:  跳转到所有贴子页面

✅实际结果: 与预期结果相符

测试代码如下: 

    @Order(2)@ParameterizedTest@CsvSource({"zhangsan, 123456"})void myAllActicleListByLogin(String username, String password) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]/a")).click();driver.findElement(By.cssSelector("#index_user_profile")).click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

⭐测试个人信息页面

❌未登录测试

场景1: 未登录状态下,点击个人中心

☑️预期结果: 直接跳转回登录界面

✅实际结果: 与预期结果相符

和前面类似, 但是测试用例不能少, 由于篇幅限制就不多演示了

登录状态显示个人信息测试

场景2:登录后点击用户头像下的个人中心,输入新昵称.....并修改,观察是否修改成功

☑️预期结果: 弹窗提示修改昵称成功

✅实际结果: 与预期结果相符

测试代码如下: 

测试代码如下: 

    @Order(3)@ParameterizedTest@CsvSource({"zhangsan, 123456, 头顶尖尖"})void updateUserMessageByLogin(String username, String password, String nickName) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]/a")).click();driver.findElement(By.cssSelector("#index_user_settings")).click();// 先清空driver.findElement(By.cssSelector("#setting_input_nickname")).clear();driver.findElement(By.cssSelector("#setting_input_nickname")).sendKeys(nickName);driver.findElement(By.cssSelector("#setting_submit_nickname")).click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

场景3:登录后点击用户头像下的个人中心,输入新密码并修改,其中两次密码一致,输入原密码也正确,观察是否跳转回登录界面

☑️预期结果: 跳转回登录界面, 强制重新登录

✅实际结果: 与预期结果相符

测试代码如下: 

    @Order(4)@ParameterizedTest@CsvSource({"zhangsan, 123456, 1234567, 123456"})void updatePasswordByLogin(String username, String password, String newPassword, String repeatPassword) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]/a")).click();driver.findElement(By.cssSelector("#index_user_settings")).click();WebElement element = driver.findElement(By.cssSelector("#settings_submit_password"));// 滚动到下方((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", element);// 确保滚动成功Thread.sleep(1000);driver.findElement(By.cssSelector("#settings_input_oldPassword")).sendKeys(password);driver.findElement(By.cssSelector("#settings_input_newPassword")).sendKeys(newPassword);driver.findElement(By.cssSelector("#settings_input_passwordRepeat")).sendKeys(repeatPassword);driver.findElement(By.cssSelector("#settings_submit_password")).click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());}

⭐测试退出

场景1:登录后,点击用户头像下的退出按钮,跳转回登录界面,退出成功

最后释放驱动对象

☑️预期结果: 跳转回登录界面

✅实际结果: 与预期结果相符

测试代码: 

    @Order(4)@ParameterizedTest@CsvSource({"zhangsan, 123456"})void exit(String username, String password) throws IOException, InterruptedException {driver.get("http://127.0.0.1:11451/sign-in.html");driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();driver.findElement(By.xpath("/html/body/div[1]/header[1]/div/div/div[3]/a")).click();driver.findElement(By.cssSelector("#index_user_logout")).click();Thread.sleep(1000);AutoTestUtil.getScreenshotAs(getClass().getName() + "_" + AutoTestUtil.currentMethodName());// 最后释放驱动对象driver.quit();}

面试:

【面试】如何实现的,以及有什么亮点?

实现方式: 

① 是根据个人项目来设计的测试用例,然后根据测试用例使用selenium4自动化测试工具

    Junit5单元测试框架结合来实现web自动化测试的(功能、步骤、技术一定要明确)

② 对于代码中的每个包都要进行概要介绍(公共属性[复用]、测试用例[根据每个页面来进行设计的],然后使用测试套件将所有测试类进行加载)

亮点:

① 使用了JUnit5中提供的注解:避免生成过多的对象,造成资源和时间的浪费,提高了自动化的执行效率。
② 只创建一次驱动对象,避免每个用例重复创建驱动对象造成时间和资源的浪费。
③ 使用参数化:保持用例的简洁,提高代码的可读性
④ 使用测试套件:降低了测试人员的工作量,通过套件一次执行所有要运行的测试用例。
⑤ 使用了等待:提高了自动化的运行效率,提高了自动化的稳定性,减小误报的可能性。
⑥ 使用了屏幕截图:方便问题的追溯以及问题的解决。
⑦ 使用了无头模式:只注重结果,可以留出屏幕。
【自动化写出来不难,但是自动化执行速度快、更好地发现问题并避免误报才是难题。(一定要测试主要功能)】

相关文章:

校园论坛系统Selenium自动化测试

本文为自动化测试 本项目自动化测试代码链接(仅供参考): 自动化测试代码 功能测试文章链接: 校园论坛系统自动化测试报告-CSDN博客 &#x1f308;自动化测试 思维导图 ​ 根据思维导图, 我们选取几个主要的功能进行自动化测试 编写代码 思路: 根据脑图进行测试用例的编写&am…...

Linux 一步部署DHCP服务

#!/bin/bash #脚本作者和日期 #author: PEI #date: 20250319 #检查root权限 if [ "$USER" ! "root" ]; then echo "错误&#xff1a;非root用户&#xff0c;权限不足&#xff01;" exit 0 fi #防火墙与高级权限 systemctl stop firewa…...

Cool Request:可以统计任意方法耗时

什么是Cool Request Cool Request是一个IDEA中的接口调试插件&#xff0c;除了可以发起基本的HTTP请求之外&#xff0c;还提供了强大的反射调用能力&#xff0c;可以绕过拦截器&#xff0c;这点广受网友的好评&#xff0c;当然伴随着还有Spring中对Scheduled注解的调用&#x…...

基于Spring Boot的图书管理系统的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

Python实战(2)-数据库支持

使用简单的纯文本文件可实现的功能有限。诚然&#xff0c;使用它们可做很多事情&#xff0c;但有时可能还需要额外的功能。你可能希望能够自动完成序列化&#xff0c;此时可求助于shelve和pickle&#xff08;类似于shelve&#xff09;​。不过你可能需要比这更强大的功能。例如…...

【工具】isolateR桑格测序数据的自动化处理、分类分析以及微生物菌株库的生成R包

文章目录 介绍代码案例Step 1: isoQC - Automated quality trimming of sequencesStep 2: isoTAX - Assign taxonomyStep 3: isoLIB - Generate strain library 参考 介绍 对分类标记基因&#xff08;如16S/18S/ITS/rpoB/cpn60&#xff09;进行桑格测序是鉴定包括细菌、古菌和…...

比特币牛市还在不在

在加密货币的风云世界里&#xff0c;比特币的一举一动始终牵动着投资者们的神经。近期比特币的涨幅动作&#xff0c;再次引发了市场对于牛市是否仍在延续的激烈讨论。 在深入探索比特币市场的过程中&#xff0c;获取全面且及时的资讯至关重要。您可以通过访问Techub News&#…...

鸿蒙下载文件保存到手机本地公共文件夹下、将本地的沙箱目录文件,保存到公共目录,鸿蒙picker save保存文件为空(0字节)的问题

1、首先将下载好的文件&#xff0c;保存到本地目录&#xff0c;这个目录是用户看不到的&#xff1b; 2、然后通过picker的save保存文件&#xff0c;这个picker&#xff0c;它只是获取公共目录uri用的 3、当picker有回调时&#xff0c;将公共目录的uri获取之后&#xff0c;把下…...

红日靶场(二)——个人笔记

靶场搭建 新增VMnet2网卡 **web&#xff1a;**需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMnet2网卡。 **PC&#xff1a;**跟web一样&#xff0c;也是需要配置两张网卡&#xff0c;分别是外网出访NAT模式和内网域环境仅主机模式下的VMn…...

口袋书签功能上新,免费使用

丰富主页面的菜单&#xff0c;操作更加便捷。 快来构建你的门户站点吧。 戳&#xff1a; 口袋书签...

Model Context Protocol - Prompts

1. 概述 Model Context Protocol (MCP) 提供了一种标准化的方式&#xff0c;使服务器能够向客户端暴露提示模板&#xff08;prompts&#xff09;。Prompts 是服务器提供的结构化消息和指令&#xff0c;用于与语言模型进行交互。客户端可以发现可用的提示、获取其内容&#xff…...

零知识证明:区块链隐私保护的变革力量

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…...

基于STC89C52的CD4511译码显示数字设计

摘要 本文深入探讨基于STC89C52单片机的数字显示系统设计,剖析CD4511译码驱动芯片工作原理,结合Proteus仿真验证功能。通过硬件电路、软件编程及原理分析,完整呈现单片机控制数码管显示的实现过程,为相关开发提供理论与实践参考。 一、引言 在单片机应用中,数码管显示是…...

MPC算法路径跟踪_Matlab实现

在机器人控制领域&#xff0c;模型预测控制&#xff08;MPC&#xff09;因其能够处理动态约束和多目标优化的特性&#xff0c;成为路径跟踪的热门方案。近期&#xff0c;我在 GitHub 上发现了 Mr.Winter 的MPC路径规划项目&#xff0c;其代码实现简洁且功能完整。本文将结合理论…...

QT Quick(C++)跨平台应用程序项目实战教程 2 — 环境搭建和项目创建

目录 引言 1. 安装Qt开发环境 1.1 下载Qt安装包 1.2 安装Qt 1.3 安装Visual Studio 2022 1.4 在Visual Studio 2022中安装Qt插件 1.5 在Visual Studio 2022中安装大模型编程助手 2. 创建Qt Quick项目 2.1 创建新项目 2.2 项目结构 2.3 运行项目 3. 理解项目代码 3…...

洛科威多功能岩棉板为环保助力,推动企业绿色可持续发展

在当今全球环保意识日益增强的背景下&#xff0c;企业工程项目在追求高效益的同时&#xff0c;也更加注重绿色可持续发展。作为建筑材料领域的佼佼者&#xff0c;洛科威公司推出的多功能岩棉板凭借其卓越的绿色环保特性&#xff0c;正逐渐成为企业工程项目领域的首选材料。 洛科…...

7.3《重力》

教会什么:重力及其三要素、重力加速度g、 培养什么:从力的三要素出发去研究一个力,用所学探究未知 课标: (二)运动和相互作用 2.2 机械运动和力 2.2.3 通过常见事例或实验,了解重力,认识力的作用效果。 (四)实验探究 4.1.6 用弹测力计测量力。 例6 测量一本物理教科书…...

虚幻基础:ue自定义类

文章目录 Gameplay Tag&#xff1a;ue标签类创建&#xff1a;其他-数据表格-gameplaytag安装&#xff1a;项目设置&#xff1a;gamePlayTag&#xff1a;gamePlay标签列表使用&#xff1a;变量类型&#xff1a;gamePlayTag primary data asset&#xff1a;ue数据类&#xff1a;通…...

88页手册上线 | 企业级本地私有化DeepSeek实战指南

DeepSeek为普通企业在低成本、高性能、安全可控的前提下私有化部署AI大模型提供了可行路径。 云轴科技ZStack全新推出《企业级本地私有化DeepSeek实战手册》&#xff08;点击免费下载&#xff09;&#xff0c;直击企业痛点&#xff0c;从7B轻量化模型到671B超大规模部署&#…...

Godot读取json配置文件

概述 在Godot 4.3中读取JSON配置文件&#xff0c;可以通过以下步骤实现&#xff1a; 步骤说明 读取文件内容&#xff1a;使用FileAccess类打开并读取JSON文件。 解析JSON数据&#xff1a;使用JSON类解析读取到的文本内容。 错误处理&#xff1a;处理文件不存在或JSON格式错…...

时序分析笔记

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、周期约束 二、建立时间和保持时间 三、时序路径 四、时序模型 前言 约束文件笔记&#xff0c;傅里叶的猫的视频。 一、周期约束 时序约束就是告诉软件输…...

【笔记】深度学习模型训练的 GPU 内存优化之旅:重计算篇

开设此专题&#xff0c;目的一是梳理文献&#xff0c;目的二是分享知识。因为笔者读研期间的研究方向是单卡上的显存优化&#xff0c;所以最初思考的专题名称是“显存突围&#xff1a;深度学习模型训练的 GPU 内存优化之旅”&#xff0c;英文缩写是 “MLSys_GPU_Memory_Opt”。…...

Deepseek使用技巧大全

还有好多人不会用&#xff0c;一个链接让你们全部学完 https://m0739kfdebc.feishu.cn/docx/LIBddUcupoIBwVxp0yGcsT77nFd?fromfrom_copylink...

redis搭建一主一从+keepalived(虚拟IP)实现高可用

redis搭建一主一从keepalived(虚拟IP)实现高可用 前提 有两台机器&#xff1a;如 10.50.3.141 10.50.3.142&#xff0c;虚拟ip如&#xff1a;10.50.3.170 安装redis&#xff08;两台机器执行&#xff09;: # 启用Remi仓库&#xff08;CentOS 7&#xff09; sudo yum install…...

6、说一下索引失效的场景?【中高频】

索引失效意味着 查询操作 不能利用索引进行数据检索&#xff0c;而是使用 全表扫描&#xff08;也就是 数据库需要从磁盘上读取表的所有数据行&#xff09;&#xff0c;从而导致性能下降&#xff0c;下面一些场景会发生索引失效 对索引使用左或者左右模糊匹配&#xff08;where…...

前端调试实战指南:从入门到高阶的完整解决方案

引言:调试的本质与价值 调试是程序员将理想代码映射到现实运行环境的关键过程。据统计,开发者平均将30%的工作时间用于调试。本指南将系统梳理现代前端调试技术体系,帮助开发者构建高效的调试工作流。 一、基础调试工具箱 1.1 浏览器开发者工具核心功能 元素调试(Elemen…...

电商多包裹与子母单发货区别

在电商发货中&#xff0c;多包裹发货和子母单是两种常见的发货方式&#xff0c;具体含义如下&#xff1a; 1. 多包裹发货 定义&#xff1a; 指一个订单中的商品因库存、尺寸或重量等原因&#xff0c;无法装入一个包裹&#xff0c;需分成多个包裹发出。 原因&#xff1a; 商品…...

程序化广告行业(28/89):基于用户旅程的广告策略解析

程序化广告行业&#xff08;28/89&#xff09;&#xff1a;基于用户旅程的广告策略解析 大家好&#xff01;一直以来&#xff0c;我都希望能和大家在技术学习的道路上携手前行、共同进步。在之前的文章里&#xff0c;我们探讨了程序化广告行业的诸多关键环节&#xff0c;这次让…...

Hugging Face模型国内镜像HF Mirror下载

直接下载 Hugging Face 开启梯子&#xff0c;一看好几个g... 我们寻找国内镜像。 访问HF-Mirror 继续上面搜索。 继续点击跟踪路径。 拼出路径。 https://hf-mirror.com/Comfy-Org/Wan_2.1_ComfyUI_repackaged/resolve/main/split_files/vae/wan_2.1_vae.safetensors 如果网…...

2025-03-19 学习记录--C/C++-C语言-单链表的结构体定义 + LNode * 和 LinkList 的区别

C语言-单链表的结构体定义 ⭐️ 一、单链表的结构体定义 &#x1f36d; typedef struct LNode { // 定义结构体 LNode&#xff0c;表示链表中的一个结点int data; // 数据域&#xff0c;存储结点的值struct LNode *next; // 指针域&#xff0c;指向下一个结点 } LN…...

【操作系统安全】任务7:服务与进程

目录 一、引言 二、服务与进程介绍 2.1 服务的概念 2.2 进程的概念 2.3 服务与进程的关系 2.4 服务与进程在网络安全中的重要性 三、LAMP 网站环境部署 3.1 LAMP 简介 3.2 LAMP 环境部署步骤 3.2.1 安装 Linux 操作系统 3.2.2 安装 Apache HTTP 服务器 3.2.3 安装 …...

AI里的RAG到底是什么?

AI大模型如deepseek本地部署的成本相对较低&#xff0c;如果要训练&#xff0c;微调大模型&#xff0c;则需要非常多的显卡&#xff0c;与很多时间&#xff0c;那一般企业无法投入那么多钱去买显卡&#xff0c;怎么办&#xff1f; 通过RAG与本地部署来提升大模型的专业知识 R…...

数据库从安装到劝退

友好的安装是数据库使用的第一步 MySQL被称为5分钟数据库。是形容安装简单。事实也是如此。RPM一下可以就把几个包安装完毕了。一个单机情况下&#xff0c;5分钟是足够的。 其他数据库PostgreSQL也差不多是这样。 而Redis这种就更快了。所以这些才能流行。 曾经数据库中安装相…...

《基于Spring Boot+Vue的智慧养老系统的设计与实现》开题报告

个人主页:@大数据蟒行探索者 一、研究背景及国内外研究现状 1.研究背景 根据1982年老龄问题世界大会联合国制定的标准,如果一个国家中超过65岁的老人占全国总人口的7%以上,或者超过60岁的老人占全国总人口的10%以上,那么这个国家将被定义为“老龄化社会”[1]。 随着国…...

PHP转GO Go语言环境搭建(Day1) 常见问题及解决方案指南

Go语言环境搭建(Day1)整理的 常见问题及解决方案指南: Go环境搭建问题排查手册 一、安装阶段问题 问题现象原因分析解决方案安装包下载失败网络问题或官网访问慢使用国内镜像下载:- Go中文网提示"Access Denied"Windows系统权限不足1. 右键安装包选择"以管理…...

VLLM专题(三十九)—自动前缀缓存(二)

前缀缓存(Prefix Caching)是一种在LLM推理中广泛使用的优化技术,旨在避免冗余的提示词(prompt)计算。其核心思想很简单——我们缓存已处理请求的键值缓存(kv-cache)块,并在新请求的前缀与之前请求相同时重用这些块。由于前缀缓存几乎是一种“免费的午餐”,并且不会改变…...

C语言每日一练——day_12(最后一天)

引言 针对初学者&#xff0c;每日练习几个题&#xff0c;快速上手C语言。第十二天。&#xff08;最后一天&#xff0c;完结散花啦&#xff09; 采用在线OJ的形式 什么是在线OJ&#xff1f; 在线判题系统&#xff08;英语&#xff1a;Online Judge&#xff0c;缩写OJ&#xff0…...

HAL库编程知识点---Can.c和Driver_can.c分层开发

在一个工程中&#xff0c;通常会把对CAN外设的操作分成底层和上层两个部分&#xff0c;从而提高代码的模块化和可维护性。一般来说&#xff1a; can.c 通常由硬件抽象层&#xff08;HAL&#xff09;或者自动生成工具&#xff08;如 CubeMX&#xff09;提供或生成。主要负责CAN硬…...

L2TP实验 作业

拓扑图 实验需求 让FW1&#xff08;PPPoE Client&#xff09;模拟拨号用户&#xff0c;向内部服务器发送建立拨号连接的请求&#xff0c;并保证连通 实验步骤 安全区域 firewall zone trust add int g1/0/0 策略 security-policy default action permit NAS int g1/…...

算法模型从入门到起飞系列——递归(探索自我重复的奇妙之旅)

文章目录 前言一、递归本质1.1 递归的要素1.2 递归特点 二、递归&迭代2.1 递归&迭代比较2.2 递归&迭代如何实现相同功能2.2.1 递归实现2.2.2 迭代实现2.2.3 性能对比 三、优雅的递归理解3.1 阶乘计算分解3.2 [DFS](https://blog.csdn.net/qq_38315952/article/deta…...

Netty源码—1.服务端启动流程二

大纲 1.服务端启动整体流程及关键方法 2.服务端启动的核心步骤 3.创建服务端Channel的源码 4.初始化服务端Channel的源码 5.注册服务端Channel的源码 6.绑定服务端端口的源码 7.服务端启动流程源码总结 5.注册服务端Channel的源码 (1)注册服务端Channel的入口 (2)注册…...

Python OCR文本识别详细步骤及代码示例

光学字符识别&#xff08;OCR&#xff09;是将图像中的文字转换为可编辑文本的技术。在Python中&#xff0c;我们可以利用多种库实现OCR功能。本文将详细介绍使用Tesseract和EasyOCR进行文本识别的步骤&#xff0c;并提供完整的代码示例。 一、OCR简介 OCR&#xff08;Optical…...

springmvc 框架学习

什么是 SpringMVC 框架 Spring MVC 是 Spring 框架的核心模块之一&#xff0c;基于 Java Servlet API 构建的 Web 层解决方案。它实现了 MVC 设计模式&#xff08;Model-View-Controller&#xff09;&#xff0c;专为开发灵活、松耦合的 Web 应用程序而设计。 在控制层框架历…...

学习threejs,构建THREE.ParametricGeometry参数化函数生成几何体

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.ParametricGeometry1…...

【华为OD-E卷 - 单词接龙 100分(python、java、c++、js、c)】

【华为OD-E卷 - 单词接龙 100分&#xff08;python、java、c、js、c&#xff09;】 题目 单词接龙的规则是&#xff1a; 可用于接龙的单词首字母必须要前一个单词的尾字母相同&#xff1b; 当存在多个首字母相同的单词时&#xff0c;取长度最长的单词&#xff0c;如果长度也相…...

美团Leaf分布式ID生成器使用教程:号段模式与Snowflake模式详解

引言 在分布式系统中&#xff0c;生成全局唯一ID是核心需求之一。美团开源的Leaf提供了两种分布式ID生成方案&#xff1a;号段模式&#xff08;高可用、依赖数据库&#xff09;和Snowflake模式&#xff08;高性能、去中心化&#xff09;。本文将手把手教你如何配置和使用这两种…...

性能测试过程实时监控分析

性能监控 前言一、查看性能测试结果的3大方式1、GUI界面报告插件2、命令行运行 html报告3、后端监听器接入仪表盘 二、influxDB grafana jmeter测试监控大屏1、原理&#xff1a;2、linux环境中influxDB 安装和配置3、jmerer后端监听器连接influxDB4、linux环境总grafana环境搭…...

【工具类】Java的 LocalDate 获取本月第一天和最后一天

博主介绍&#xff1a;✌全网粉丝22W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

Eclipse 创建 Java 类

Eclipse 创建 Java 类 引言 Eclipse 是一款功能强大的集成开发环境(IDE),被广泛用于 Java 开发。本文将详细介绍如何在 Eclipse 中创建 Java 类,包括配置开发环境、创建新项目、添加类以及编写类代码等步骤。 配置 Eclipse 开发环境 1. 安装 Eclipse 首先,您需要在您…...

Centos编译升级libcurl

Centos编译升级libcurl ‌下载最新版源码包安装编译依赖配置编译选项如果报错&#xff1a;通过 EPEL 仓库安装手动源码编译安装 如果报错&#xff1a;安装Brotli 开发库 如果报错&#xff1a;方法一&#xff1a;安装 libpsl-devel 依赖通过 EPEL 仓库安装重新运行 configure 方…...