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

个人博客系统测试

  • 一、项目背景
    • 1.1 技术背景
    • 1.2 功能背景
  • 二、自动化测试
    • 2.1 什么是自动化测试
    • 2.2 通过使用selenium进行自动化测试的编写(Java实现)
    • 2.3 编写测试用例,执行自动化测试
      • 2.3.1 输入用户名:test,密码:123,登录成功
      • 2.3.2 登录成功后,没有文章,点击写博客,发布博客
      • 2.3.3 发布文章后,文章列表页文章数不为0
      • 2.3.4 校验博客
      • 2.4.5 在文章列表页,发布者可以进行文章修改操作
      • 2.4.6 在文章列表页,发布者可以进行文章删除操作
      • 2.4.7 注销账号,退出登录
      • 2.4.8 输入用户名:testt,密码:123,登录失败
      • 2.4.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. 注销:点击注销,会退出当前账号。

二、自动化测试

2.1 什么是自动化测试

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

2.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();
}

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

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

2.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. 输入用户名test
    webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    // 3. 输入密码123
    webDriver.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 获取当前页url
    String 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);
}

2.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. 添加标题 test1
    webDriver.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);
}

2.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);
}

2.3.4 校验博客

  • 获取元素

在这里插入图片描述


  • 测试代码
 @Test
 void 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("测试通过");
     } else
         System.out.println("测试未通过");
 }

2.4.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=
    // 获取修改页面url
    webDriver.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);
}

2.4.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.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);
    // 5. 判断若第一条博客标题不是自动化测试,则测试通过
    String newTitle = webDriver.findElement(By.cssSelector("#artListDiv > div > div.title")).getText();
    Assertions.assertNotEquals("自动化测试",newTitle);
}

2.4.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);
}

2.4.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. 输入用户名testt
    webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    // 3. 输入密码123
    webDriver.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 获取当前页url
    String currentUrl = webDriver.getCurrentUrl();
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    //  5.2 与预期url("http://localhost:58081/login.html")对比,一致则测试通过
    Assertions.assertEquals(blogListUrl, currentUrl);
}

2.4.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. 输入用户名test
    webDriver.findElement(By.cssSelector("#username")).sendKeys(username);
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    // 3. 输入密码1234
    webDriver.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 获取当前页url
    String currentUrl = webDriver.getCurrentUrl();
    webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    //  5.2 与预期url("http://localhost:58081/login.html")对比,一致则测试通过
    Assertions.assertEquals(blogListUrl, currentUrl);
}

三、测试用例通过


在这里插入图片描述


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/531903.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习图像处理04:图像分类模型训练实战——动物分类

这篇博文不涉及理论知识&#xff0c;主要通过一个完整的深度学习模型训练流程&#xff0c;直观地了解深度学习图像分类任务。有关理论的部分&#xff0c;之前几篇博文已经涉及基础部分&#xff0c;之后也会对一些理论进行补充。 本文将结合代码&#xff0c;主要介绍三部分内容…

halcon缺陷检测-印刷品检测(差异化模型),键盘字符缺陷检测

前言 在实际项目中&#xff0c;印刷品缺陷检测是缺陷检测中的难点项目。通常印刷品检测往往具备缺陷小&#xff0c;缺陷所在位置不固定&#xff0c;出现少印或者多印的情况。并且由于产线原因&#xff0c;大量的印刷品在视野中的大小并不是完全一致的&#xff0c;可能出现细微…

【UE5 C++】访问修饰符public/protected/private继承

限制类与类之间访问级别的方法 public 在类中创建一个public的部分&#xff0c;即" public: "&#xff0c;public之下的所有内容都是公共的,可以在类之间访问 private&#xff08;最常见&#xff09; 如若没有指明修饰符&#xff0c;则默认为private 不能在类的外…

文本处理常见命令

目录 前言-了解Linux目录结构 一、cat-查看文件内容 1.表现形式 2.常用选项 3.示例 二、more-查看文件内容 1.表现形式 2.交互操作方法 3.示例 三、less-查看文件内容 1.表现形式 2.交互操作方法 四、head-从头查看文件内容 五、tail-从尾查看文件内容 六、wc-统…

【石上星光】context,go的上下文存储并发控制之道

目录 1 引言2 What&#xff1f;3 How&#xff1f; 3.1 用法一、上下文数据存储3.2 用法二、并发控制 3.2.1 场景1 主动取消3.2.2 场景2 超时取消 3.3 用法三、创建一个空Context&#xff08;emptyCtx&#xff09; 4 Why&#xff1f; 4.1 go中的上下文思想 4.1.1 上下文是什么…

17 - Games101 - 笔记 - 材质与外观

**17 **材质与外观 材质与BRDF 自然界中的材质&#xff1a;丝绸、头发、蝴蝶翅膀表面、寿司表面等等 图形学中的材质&#xff1a;同一个模型之所以渲染出不同结果的原因就是因为材质。在图形学中是给不同的物体指定不同的材质&#xff0c;知道它们如何和光线作用后就能正确的…

体验Docker快速部署微信机器人

找到一个 Docker 部署微信机器人的镜像&#xff0c;简单测试一下。 1 使用 Docker 部署 1.1 拉取最新镜像 docker pull dannicool/docker-wechatbot-webhook1.2 Docker 部署 docker run -d --name wxBotWebhook -p 3001:3001 \ -v ~/wxBot_logs:/app/log \ dannicool/docker…

【C++基础】运算符和流程控制语句

C中的运算符和流程控制语句 一、运算符1. C和Java在通用运算符中的不同之处对比2. C中的位运算符2.1 移位运算符2.2 位逻辑运算符 3. 运算时的类型转换总结3.1 隐式类型转换3.2 显式类型转换&#xff08;强制类型转换&#xff09; 4. 注意 二、流程控制语句1. C和Java在通用流程…

网工内推 | 安全运维、服务工程师,软考中级、CISP优先,六险一金

01 华成峰科技 招聘岗位&#xff1a;安全运维工程师 职责描述&#xff1a; 1、负责安全产品的运维管理&#xff0c;包括设备升级变更、策略配置优化、设备巡检等&#xff1b; 2、负责7*24小时安全监控与应急响应&#xff0c;包括态势感知日志监测、安全事件分析及处置等&#…

【Keil5-报错】

Keil5-报错 ■ 调试烧录出现问题■ 烧录程序失败■ 编译报错 .\Objects\stm32h7_tms.axf: Error: L6218E: Undefined symbol __heap_base (referred from alloc.o).■ Keil5 load 出错■ No Space in execution regions with .ANY selector matching startup ...■ Execution r…

selenium自动化测试实战

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

SSD涨价停不下来!

随着HBM内存产能短缺问题的出现&#xff0c;存储市场正遭遇另一波供应短缺。在2021年存储市场陷入低迷后&#xff0c;SSD价格已连续下滑约两年。面对市场变化&#xff0c;存储厂商减少了NAND闪存的生产。随着减产策略的有效执行&#xff0c;需求部分回升&#xff0c;导致SSD供应…

Hot100【十一】:最大子数组和

// 定义dp&#xff1a;以i结尾的最大子数组和 dp[i] max(dp[i-1] nums[i],nums[i]) class Solution {public int maxSubArray(int[] nums) {// 1. 不需要特殊处理// 2. 定义dpint[] dp new int[nums.length];dp[0] nums[0];int maxResult nums[0];// 3. dp递推for (int i …

Oracle 在线回缩表

Oracle 在线回缩表 conn scott/tiger DROP TABLE EMP1 PURGE; CREATE TABLE EMP1 AS SELECT * FROM EMP; alter table emp1 enable row movement; -- 启动回缩特性 insert into emp1 select * from emp1; / / commit; -- 增加到14000行 -- 分析表的结构 analyz…

Vue2 —— 学习(五)

一、生命周期 &#xff08;一&#xff09;引入案例 我们想让一行文字按一定频率逐渐变得透明 1. Vue 实例外写法 函数写在 Vue 实例外面也能实现但是不推荐 <body><div id"root"><h2 :style"{opacity}">欢迎学习Vue</h2><…

ELK大型日志收集分析系统

目录 一、 ELK日志分析系统 1.1ELK介绍 1.2ELK各组件介绍 1.2.1ElasticSearch 1.2.2Kiabana 1.2.3Logstash 1.2.4可以添加的其它组件 1.2.4.1Filebeat filebeat 结合logstash 带来好处 1.2.4.2缓存/消息队列&#xff08;redis、kafka、RabbitMQ等&#xff09; 1.2.4…

100道面试必会算法-21-二叉树的最近公共祖先

100道面试必会算法-21-二叉树的最近公共祖先 题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且…

springcloud==springboot3.X+JDK21

2024年新版springcloud springboot3.X JDK21 ROADMAP 配套代码地址 GitHub - hebian1994/cloud2024

外包干了3天,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;19年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

最祥解决python 将Dataframe格式数据上传数据库所碰到的问题

碰到的问题 上传Datafrane格式的数据到数据库 会碰见很多错误 举几个很普遍遇到的问题(主要以SqlServer举例) 这里解释下 将截断字符串或二进制数据 这个是字符长度超过数据库设置的长度 然后还有字符转int失败 或者字符串转换日期/或时间失败 这个是碰到的需要解决的最多的问…