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

【软件测试】个人博客系统测试

个人博客系统测试

  • 一、项目背景
    • 1.1 技术背景
    • 1.2 功能背景
  • 二、 测试用例编写
  • 三、自动化测试
    • 3.1 什么是自动化测试
    • 3.2 通过使用selenium进行自动化测试的编写(Java实现)
    • 3.3 编写测试用例,执行自动化测试
      • 3.3.1 输入用户名:test,密码:123,登录成功
      • 3.3.2 登录成功后,没有文章,点击写博客,发布博客
      • 3.3.3 发布文章后,文章列表页文章数不为0
      • 3.3.4 校验博客
      • 3.3.5 在文章列表页,发布者可以进行文章修改操作
      • 3.3.6 在文章列表页,发布者可以进行文章删除操作
      • 3.3.7 注销账号,退出登录
      • 3.3.8 输入用户名:testt,密码:123,登录失败
      • 3.3.9 输入用户名:test,密码:1234,登录失败
  • 四、测试用例通过

一、项目背景

1.1 技术背景


  1. 我的博客系统主要是通过前端HTML+后端SpringBoot实现了一个博客的基本的功能。
  2. 前端主要用到了HTML+CSS,通过Jquery的方式向后端请求数据。
  3. 后端主要用到了SpringBoot的框架,整合了MyBatis,通过MyBatis从数据库中查询数据响应给前端。
  4. 项目中,用户在注册保存密码的时候,后端会进行md5加盐算法进行加密处理,保证了密码的安全性。
  5. 相应数据的时候,封装了一个统一的返回格式,便于前后端的交互及数据的获取。
  6. 用户登录后,为了保持用户在线的持久化,在用户登录成功时,会将用户的身份信息存储在session中,这样在每次访问一个页面的时候,会对当前用户的身份信息进行校验,每次访问时前端会传来一个seeionId,后端通过这个sessionId拿到用户的信息,然后校验,通过后响应给前端数据,否则,提示用户登录。

1.2 功能背景


  1. 注册:新用户进行注册,后端会进行校验,如果注册的用户已存在,会提示用户已存在,如果两次密码不一致,会提示用户重新输入;如果注册成功,会跳转到登录页面。
  2. 登录:用户输入用户名和密码,登录成功,跳转到个人博客列表页,显示当前用户已发布的博客信息。
  3. 发布博客:点击发布博客,会跳转到博客添加页,输入博客内容,发布博客,然后跳转到博客列表页,展示刚刚发布的博客。
  4. 博客详情页:点击博客详情,跳转到博客详情页,展示了博客的标题、内容、发布时间、阅读量、作者信息(作者用户名、作者发布文章数)。
  5. 总博客列表页:显示所有用户发布的博客,会以分页的形式展示,我设置的默认是每页显示两条,会有总页数,当前所在页。
  6. 修改博客:在个人博客列表中,可以点击修改某一篇文章,进入博客修改页重新进行编辑,然后发布修改。
  7. 删除博客:在个人博客列表中,可以点击删除某一篇文章。
  8. 游客登录:如果用户未登录,作为游客可以访问博客列表页(主页),可以查看所有用户发布的博客内容及博客详情,但是不能发布文章。
  9. 注销:点击注销,会退出当前账号。

二、 测试用例编写

根据博客系统的功能,兼容,界面,易用,性能,安全等方面设计了如下测试用例


在这里插入图片描述


三、自动化测试

3.1 什么是自动化测试

自动化测试简单来说就是使用自动测试工具和自动测试脚本来完成指定的测试任务,测试启动过程不需要人为参与,但自动化测试之前的准备需要人工手动配置好。它是一种将重复性的、繁琐的测试任务交给计算机自身来执行,它可以大幅度提高测试效率、减少测试人员的成本、提高测试覆盖率和准确性。

3.2 通过使用selenium进行自动化测试的编写(Java实现)

    1. 添加依赖到pom.xml文件:
<!--selenium控制浏览器-->
<dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.7.2</version>
</dependency>
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version>
</dependency>
<!--测试-->
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.10.1</version>
</dependency>
    1. 封装初始化浏览器驱动:
/*** 初始化浏览器驱动*/
@BeforeAll  //在所有测试方法执行之前执行
static void setUp() {//允许所有请求chromeOptions.addArguments("--remote-allow-origins=*");//取消 chrome正受到自动测试软件的控制的信息栏ChromeOptions options = new ChromeOptions();options.setExperimentalOption("excludeSwitches", new String[]{"enable-automation"});//创建浏览器驱动webDriver = new ChromeDriver(chromeOptions);
}
    1. 关闭浏览器
/*** 关闭浏览器*/
@AfterAll // 在所有测试方法执行完之后执行
static void tearDown() {webDriver.quit();
}

3.3 编写测试用例,执行自动化测试

前提说明: 我的博客是在本地运行的,如果要测试线上的某个系统,可以把获取页面的url换成相应的网址即可。

3.3.1 输入用户名:test,密码:123,登录成功

  • 获取元素:

在这里插入图片描述


  • 测试代码:
/*** 输入用户名:test,密码:123,登录成功*/
@Order(1)//设置执行顺序,但我用着好像不管用
@ParameterizedTest
@CsvFileSource(resources = "loginSuccess.csv")
void loginTest(String username,String password,String blogListUrl) {// 1. 打开博客登录页面webDriver.get("http://localhost:58081/login.html");//智能等待,如果在这次等待期间错误,则会抛出异常webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 2. 输入用户名testwebDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 3. 输入密码123webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 4. 点击提交按钮webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//可能会有弹窗webDriver.switchTo().alert().accept();// 5. 跳转到列表页//  5.1 获取当前页urlString currentUrl = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//  5.2 与预期url("http://localhost:58081/myblog_list.html")对比,一致则测试通过Assertions.assertEquals(blogListUrl, currentUrl);// 6. 列表页展示用户名是test//  6.1 用户名是test,测试通过,否则不通过webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);String currentUerName = webDriver.findElement(By.cssSelector("#username")).getText();Assertions.assertEquals(currentUerName,username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
}

3.3.2 登录成功后,没有文章,点击写博客,发布博客


  • 点击写文章:

在这里插入图片描述


  • 校验url:

在这里插入图片描述


  • 测试代码:
@Test
void publishTest() {// 1.打开文章列表页webDriver.get("http://localhost:58081/myblog_list.html");// 2. 没有发布博客,点击添加webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();// 3. 添加标题 test1webDriver.findElement(By.cssSelector("#title")).sendKeys("test1");// 5. 点击发布文章webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();// 6. 跳转到博客列表页  “http://localhost:58081/myblog_list.html”webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);String currentUrl = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals("http://localhost:58081/myblog_list.html",currentUrl);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 7. 判断若第一条博客标题为test1,则测试通过String newTitle = webDriver.findElement(By.cssSelector("#artListDiv > div > div.title")).getText();Assertions.assertEquals("test1",newTitle);
}

3.3.3 发布文章后,文章列表页文章数不为0

  • 获取元素:
    在这里插入图片描述

  • 测试代码:
@Test
void blogCountTest() {//判断当前页文章数量int size = webDriver.findElements(By.cssSelector("#artListDiv")).size();// 不为0则测试通过webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertNotEquals(0,size);
}

3.3.4 校验博客

  • 获取元素

在这里插入图片描述


  • 测试代码
 @Testvoid checkBlogTest() {// 1.打开文章列表页webDriver.get("http://localhost:58081/myblog_list.html");//博客标题String title = webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.title")).getText();//博客发布时间String time = webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.date")).getText();Assertions.assertEquals("test1",title);//如果是2024年发布的,则测试通过if (time.contains("2024")) {System.out.println("测试通过");} elseSystem.out.println("测试未通过");}

3.3.5 在文章列表页,发布者可以进行文章修改操作


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


  • 测试代码
@Test
void updateBlogTest() throws InterruptedException {// 1.打开文章列表页webDriver.get("http://localhost:58081/myblog_list.html");// 2.判断当前登录用户是否是test//  根据列表页个人信息进行判断webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);String currentUerName = webDriver.findElement(By.cssSelector("#username")).getText();Assertions.assertEquals("test",currentUerName);webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//  3.执行到这里,说明当前登录用户是test,可以进行修改操作//    点击修改,开始修改文章webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > a:nth-child(5)")).click();// 4.跳转到修改文章页面  http://localhost:58081/blog_edit.html?blogId=// 获取修改页面urlwebDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);String editPageUrl = webDriver.getCurrentUrl();if (editPageUrl.contains("http://localhost:58081/blog_edit.html?blogId=")) {System.out.println("测试通过!");} else {System.out.println("测试不通过!");}webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);// 5. 修改文章内容// 通过JS将标题进行修改((JavascriptExecutor)webDriver).executeScript("document.getElementById(\"title\").value = \"自动化测试\"");webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);// 6. 点击修改文章webDriver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();// 7. 跳转到博客列表页  “http://localhost:58081/myblog_list.html”// 会有弹窗// 这里强制睡3s,要不然这个弹窗会检测不出来sleep(3000);webDriver.switchTo().alert().accept();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);String currentUrl = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals("http://localhost:58081/myblog_list.html",currentUrl);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 8. 判断若第一条博客标题为自动化测试,则测试通过String newTitle = webDriver.findElement(By.cssSelector("#artListDiv > div > div.title")).getText();Assertions.assertEquals("自动化测试",newTitle);
}

3.3.6 在文章列表页,发布者可以进行文章删除操作

  • 操作步骤
    在这里插入图片描述

在这里插入图片描述


@Test
void deleteBlogTest() throws InterruptedException {// 1.打开文章列表页webDriver.get("http://localhost:58081/myblog_list.html");// 2.判断当前登录用户是否是test//  根据列表页个人信息进行判断webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);String currentUerName = webDriver.findElement(By.cssSelector("#username")).getText();Assertions.assertEquals("test",currentUerName);webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//  3.执行到这里,说明当前登录用户是test,可以进行删除操作//    点击修改,开始删除文章webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > a:nth-child(6)")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//可能有弹窗sleep(3000);webDriver.switchTo().alert().accept();// 4. 校验页面 http://localhost:58081/myblog_list.htmlwebDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);String currentUrl = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals("http://localhost:58081/myblog_list.html",currentUrl);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 5. 判断若第一条博客标题不是自动化测试,则测试通过String newTitle = webDriver.findElement(By.cssSelector("#artListDiv > div > div.title")).getText();Assertions.assertNotEquals("自动化测试",newTitle);
}

3.3.7 注销账号,退出登录

  • 操作步骤
    在这里插入图片描述

在这里插入图片描述


  • 测试代码
@Test
void logOffTest() throws InterruptedException {// 1. 点击注销按钮,退出博客webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();//可能有弹窗,直接通过,跳转到登录页面sleep(3000);webDriver.switchTo().alert().accept();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 2. 判断当前页面是否是登录页面String currentUrl = webDriver.getCurrentUrl();Assertions.assertEquals("http://localhost:58081/login.html",currentUrl);
}

3.3.8 输入用户名:testt,密码:123,登录失败

  • 操作步骤
    在这里插入图片描述

  • 测试代码
@ParameterizedTest
@CsvFileSource(resources = "loginFail1.csv")
void loginFail1(String username,String password,String blogListUrl) {// 1. 打开博客登录页面webDriver.get("http://localhost:58081/login.html");//智能等待webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 2. 输入用户名testtwebDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 3. 输入密码123webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 4. 点击提交按钮webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//可能会有弹窗webDriver.switchTo().alert().accept();// 5. 不进行跳转//  5.1 获取当前页urlString currentUrl = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//  5.2 与预期url("http://localhost:58081/login.html")对比,一致则测试通过Assertions.assertEquals(blogListUrl, currentUrl);
}

3.3.9 输入用户名:test,密码:1234,登录失败

  • 操作步骤
    在这里插入图片描述

  • 测试代码
@ParameterizedTest
@CsvFileSource(resources = "loginFail2.csv")
void loginFail2(String username,String password,String blogListUrl) {// 1. 打开博客登录页面webDriver.get("http://localhost:58081/login.html");//智能等待webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 2. 输入用户名testwebDriver.findElement(By.cssSelector("#username")).sendKeys(username);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 3. 输入密码1234webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 4. 点击提交按钮webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//可能会有弹窗webDriver.switchTo().alert().accept();// 5. 不进行跳转//  5.1 获取当前页urlString currentUrl = webDriver.getCurrentUrl();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//  5.2 与预期url("http://localhost:58081/login.html")对比,一致则测试通过Assertions.assertEquals(blogListUrl, currentUrl);
}

四、测试用例通过


在这里插入图片描述


相关文章:

【软件测试】个人博客系统测试

个人博客系统测试 一、项目背景1.1 技术背景1.2 功能背景 二、 测试用例编写三、自动化测试3.1 什么是自动化测试3.2 通过使用selenium进行自动化测试的编写&#xff08;Java实现&#xff09;3.3 编写测试用例&#xff0c;执行自动化测试3.3.1 输入用户名:test,密码:123&#x…...

20240410解决OK3588-C的核心板刷机之后无法启动的问题

20240410解决OK3588-C的核心板刷机之后无法启动的问题 2024/4/10 19:38 1、编译OK3588的LINUX/Buildroot&#xff1f;forlinxubuntu: ~/3588/OK3588_Linux_fs$ sudo ./build.sh BoardConfig-linuxfs-ok3588.mk 2、进行全编译 forlinxubuntu: ~/3588/OK3588_Linux_fs$ sudo ./bu…...

仅需三步就能成为大语言模型Prompt Engineer提示词工程大神

AI Prompt Engineer(提示词工程)是当下GenAI行业最热门的话题&#xff0c;它是利用有效的AI模型交互提示技术&#xff0c;引导大语言模型生成更高质量、更准确、更相关的回应。相对于预训练和微调&#xff0c;提示词工程不需要标注数据和训练模型&#xff0c;极大的节约了时间和…...

RuleEngine规则引擎底层改造AviatorScript 之公式规则

前情提要&#xff0c;看上一个文章&#xff0c;具体要实现的效果就是 当然上来的问题就是前端的问题&#xff0c;这个框首先他们用的是富文本&#xff0c;富文本传到后台的结果是前端脚本&#xff0c;带着h5的标签&#xff0c;后面改成了这个&#xff0c;当时这个东西其实和后…...

Vue项目(H5)与微信小程序来回跳转

新建H5页面 在小程序里面新建一个名为H5的文件夹&#xff0c;以及H5页面 H5.WXML <web-view src"{{h5Url}}" bindmessage"handleGetMessage"></web-view>H5.JSdata: { h5Url:https://xxx.com/login 要跳转的H5页面},H5回来的回调方法handleG…...

设计模式-单一职责原则

基本介绍 对类来说的&#xff0c;即一个类应该只负责一项职责。如类A负责两个不同的职责&#xff0c;职责1&#xff0c;职责2.当职责1需求变更而改变A时&#xff0c;可能造成职责2执行错误&#xff0c;所以需要将类A的粒度分解为A1&#xff0c;A2 应用实例 方案1 public cl…...

vue和nunjucks的变量插值的形式{{}}冲突

Nunjucks 中修改配置 const nunjucks require(nunjucks);const template_old nunjucks.renderString(template_old: Hello, {{name}}!, { name: World }); console.log(template_old); // 配置 Nunjucks 环境 nunjucks.configure({tags: {variableStart: $(, // 设置变量起始…...

多语言婚恋交友APP开发流程一览

近年来&#xff0c;随着全球化的发展和人们对跨文化交流的需求增加&#xff0c;多语言婚恋交友APP的需求逐渐增长。开发这类APP需要考虑到不同语言和文化下用户的需求&#xff0c;涉及到一系列独特的流程和挑战。本文将从专家角度为您解析多语言婚恋交友APP的开发流程&#xff…...

RUM 最佳实践-交互延迟的探索与发现

FID 在互联网高速发展的时代&#xff0c;用户体验已成为企业竞争的关键所在。网页性能作为用户体验的重要组成部分&#xff0c;直接影响着用户的满意度和工作效率。First Input Delay&#xff08;FID&#xff09;作为衡量网页性能的重要指标&#xff0c;越来越受到业界关注。今…...

spring boot 集成 flyway依赖 做数据库迁移,让部署没烦恼

flyway 是一个敏捷工具&#xff0c;用于数据库的移植。采用 Java 开发&#xff0c;支持所有兼容 JDBC 的数据库。 主要用于在你的应用版本不断升级的同时&#xff0c;升级你的数据库结构和里面的数据。 还是直接上代码 第一步&#xff1a; <!-- Flyway 数据库迁移 依赖 他…...

TCP协议--传输机制

TCP协议原理 TCP协议是对数据传输提供的一个管控机制&#xff0c;主要体现在可靠和效率两个方面&#xff0c;即在保证数据可靠传输的情况下尽可能的提高效率 可靠传输机制 确认应答机制 向对方发送一个数据报&#xff0c;对方要返回一个确认应答的数据报 实现的方式&#x…...

句柄ros::NodeHandle nh(“~“)与nh对launch文件参数配置(param)的影响

ros::NodeHandle nh("~"); 改为&#xff1a; ros::NodeHandle nh; 即可 /*************************分割线 ************************/ 如果原本是&#xff1a; ros::NodeHandle nh;可以改成&#xff1a; ros::NodeHandle nh("~"); 试试...

C++_List的学习

1.概述 1. list 是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代 2. list 的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素 3. list…...

centos 7.9 nginx本地化安装,把镜像改成阿里云

1.把centos7.9系统切换到阿里云的镜像源 1.1.先备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup1.2.下载新的CentOS-Base.repo配置文件 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo特别…...

JVM规范中的运行时数据区

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;每天一个知识点 ✨特色专栏&#xff1a…...

Stable Diffusion文生图技术详解:从零基础到掌握CLIP模型、Unet训练和采样器迭代

文章目录 概要Stable Diffusion 底层结构与原理文本编码器&#xff08;Text Encoder&#xff09;图片生成器&#xff08;Image Generator&#xff09; 那扩散过程发生了什么&#xff1f;stable diffusion 总体架构主要模块分析Unet 网络采样器迭代CLIP 模型 小结 概要 Stable …...

SDK-0.7.8-Release-实体管理 - ApiHug-Release

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace 更多精彩…...

3. DAX 时间函数-- DATE 日期--一生二,二生三,三生万物

在数据分析过程中&#xff0c;经常需要从一个数据推到另外一个数据&#xff0c;日期数据也是如此&#xff0c;需要从一个日期推到另外一个相关的日期&#xff0c;或者从一群日期推到另外一个相关的日期/一群相关的日期。这一期说的就是日期之间彼此推衍的函数&#xff0c;会比之…...

c 解数独(通用方法,适用于9×9 数独)

折腾了一周时间&#xff0c;终于搞定99数独通用方法 思路&#xff1a;1.生成每行空位的值&#xff0c;也就是1-9中除去非0的数。 2.用行&#xff0c;列&#xff0c;宫判断每行中每个空位的最小取值范围后再重新生成每行。 3.随机提取生成的9行&#xff0c;判断每列之和是否等…...

一篇文章深入学习Java的AQS(AbstractQueuedSynchronizer)

深入理解AQS的设计和工作机制 Oracle官方文档中的AbstractQueuedSynchronizer部分讲解 AbstractQueuedSynchronizer&#xff08;简称AQS&#xff09;是Java并发包中的一个基础框架&#xff0c;它为实现依赖单个原子变量来表示状态的同步器提供了可靠的基础。这个框架被广泛用…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成

一个面向 Java 开发者的 Sring-Ai 示例工程项目&#xff0c;该项目是一个 Spring AI 快速入门的样例工程项目&#xff0c;旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计&#xff0c;每个模块都专注于特定的功能领域&#xff0c;便于学习和…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...