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

问卷系统测试报告

目录

一、项目背景

1. 项目背景与意义

2.项目概述

2.1 已实现的主要功能包括

2.2 当前系统存在的不足

3.测试目标

4.测试项目相关信息

二、测试安排

三、测试分类

(一)自动化功能测试

1.编写 Web 测试用例

2.搭建 Python 自动化项目

2.1 环境配置准备

2.2 封装公共驱动对象

2.3 分模块编写 tests 测试用例

2.4 自动化执行过程中发现的业务缺陷

(二)性能测试

1. 模拟并发访问项目事务各页面

2. 高并发下系统产生的问题观测与验证

3. 我的项目模块页面请求超长耗时问题验证

四、遗留风险

五、测试结果评估

项目名称

问卷系统

版本号

V1.0

发布类型

迭代发布

测试负责人

本人

测试完成日期

2026.06.28

联系方式

-

评审人

前端开发、后端开发、测试、产品、交互

批准人

产品负责人

一、项目背景

1. 项目背景与意义

问卷在线测评系统面向企业 / 教学场景,提供在线问卷、考试、题库、练习管理一体化能力,支持快速创建单选类试卷、批量导入题目、在线作答练习、数据统计分析。本次迭代完成全模块功能开发,同步开展手工功能测试、Python+Selenium UI 自动化回归、JMeter 性能专项测试,验证系统可用性、稳定性与加载性能,保障线上分级发布质量

2.项目概述

2.1 已实现的主要功能包括

  • 用户账号体系:登录、注册、个人信息 / 密码修改
  • 首页数据看板:用户统计、我的考试快捷入口、快速创建试卷
  • 我的项目模块:试卷列表、新建问卷 / 考试、题目编辑、批量导入题目
  • 我的练习模块:练习记录筛选、题库切换、开始练习作答
  • 题库中心:自定义题库、题目管理、笔记记录、题库新增查询
  • 模板广场:自定义创建模板、查询已有模板
  • 系统管理:组织机构树、岗位管理、字典配置、个人 AI 设置
  • 配套能力:页面路由跳转、表单校验、弹窗交互、表格筛选、文件上传

2.2 当前系统存在的不足

  • 仅支持单选批量导入,不支持多选、简答等题型批量录入
  • 作答无自动保存功能,切页 / 刷新会丢失答题进度
  • 无用户操作日志、试卷修改记录查询功能

3.测试目标

  • 自动化测试:基于 Python+Selenium 搭建回归脚本,全覆盖 7 大业务模块,验证正向、异常流程,阻断 / 严重缺陷清零,手工用例 100% 通过
  • 性能专项测试:使用 JMeter 压测核心接口,定位我的项目列表慢查询根源,验证系统并发承载能力;
  • 缺陷闭环:所有业务 bug 同步反馈开发优化,自动化脚本兼容页面交互问题

4.测试项目相关信息

  • 被测系统地址: http://49.235.61.184:8080
  • 自动化代码仓库:https://gitee.com/dwaekkiyo/king-cram-atuo-test
  • 配套文档:《需求文档》《技术文档》《测试计划》《系统测试范围思维导图》

二、测试安排

模块

子模块

提测时间

工时

排期

进度

备注

用户模块

登录功能

06.19

0.5d

06.19

测试完成

正向 / 异常登录全覆盖

用户模块

注册功能

06.19

0.5d

06.19

测试完成

多组异常注册用例校验

首页模块

用户信息、统计数据、我的考试、快速创建问卷 / 考试

06.20

0.5d

06.20

测试完成

页面渲染、表格工具栏交互

我的练习

练习列表、筛选、表格密度、列配置、题库练习切换

06.20

0.8d

06.20

测试完成

筛选、跳转、表格配置全流程

我的项目

项目列表、在线考试创建、单选题目编辑、批量导入选项

06.21

1d

06.21

测试完成

问卷 / 考试编辑器完整流程

题库中心

我的题库、问题管理、我的笔记、题库新增查询

06.22

0.8d

06.22

测试完成

下拉选择、表单新增校验

系统管理

组织机构、岗位管理、字典管理、个人设置(基础 / 安全 / AI)

06.23

1.2d

06.23

测试完成

弹窗表单、密码修改、树选择组件

自动化回归

全核心页面自动化脚本开发调试

06.20-06.23

2d

06.23

测试完成

Python Selenium 自动化框架

三、测试分类

(一)自动化功能测试

自动化测试演示

1.编写 Web 测试用例

2.搭建 Python 自动化项目

2.1 环境配置准备

安装 Selenium、WebDriver 等依赖库

2.2 封装公共驱动对象

Utils为工具类,用来封装上述方法:driver,统一等待、截图、点击工具方法

# 创建一个浏览器对象 import datetime import os import sys from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager class Driver: driver = "" def __init__(self): options = webdriver.ChromeOptions() # ========== 新增屏蔽密码泄露弹窗全套配置 ========== # 1. 禁用密码泄露检测核心功能 options.add_argument("--disable-features=PasswordLeakDetection") options.add_argument("--disable-password-leak-detection") # 2. 关闭密码管理器、保存密码提示 prefs = { "credentials_enable_service": False, "profile.password_manager_enabled": False, "profile.password_manager_leak_detection": False, "profile.enabled_password_breach_detection": False } options.add_experimental_option("prefs", prefs) # 3. 额外屏蔽Chrome自动化常见弹窗、信息栏 options.add_argument("--disable-infobars") options.add_argument("--disable-save-password-bubble") options.add_argument("--disable-password-manager") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option("useAutomationExtension", False) # ================================================= self.driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) self.driver.implicitly_wait(5) # 窗口最大化,避免页面元素被裁切 self.driver.maximize_window() def getScreeShot(self): # 创建屏幕截图 # 图片文件名称:./2024-05-08-173456.png dirname = datetime.datetime.now().strftime("%Y-%m-%d") # 判断dirname文件夹是否已经存在,若不存在则创建文件夹 if not os.path.exists("../images/"+dirname): os.mkdir("../images/"+dirname) # 图片路径:../images/调用方法-2024-05-08/2024-05-08-173456.png # 加上调试函数名称 filename = sys._getframe().f_back.f_code.co_name+"-"+datetime.datetime.now().strftime("%Y-%m-%d-%H%M%S")+".png" self.driver.save_screenshot("../images/"+dirname+"/"+filename) # 公共获取用户名 def get_name(self): return "mms" # 公共获取用户账号 def get_username(self): return "1313" # 公共获取密码 def get_pwd(self): return "123456" KingCramDriver = Driver()
2.3 分模块编写 tests 测试用例
tests/ ├─ KingCramLogin.py # 登录页面测试脚本 ├─ KingCramRegister.py # 注册页面测试脚本 ├─ KingCramHomeTest.py # 首页页面测试脚本 ├─ KingCramMyPracticeTest.py # 我的练习模块测试脚本 ├─ KingCramMyProjectTest.py # 我的项目模块测试脚本 ├─ KingCramQuestionBankCenterTest.py # 题库中心模块测试脚本 ├─ KingCramSystemManageTest.py # 系统管理模块测试脚本 ├─ KingCramTemplateSquareTest.py # 模板广场页面脚本 └─ RunTest.py # 统一执行测试入口

此处仅放置首页代码作为展示:

import time from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from comm.Utils import KingCramDriver # ’首页‘界面测试 class KingCramHomeTest: url = "" driver = "" def __init__(self): self.url = "http://49.235.61.184:8080/home" self.driver = KingCramDriver.driver # self.driver.get(self.url) time.sleep(5) # ====================== 校验用户部分渲染 ====================== def UserInfoDisplayCheckTest(self): # 测试用户头像已经渲染 avatar = self.driver.find_element(By.CSS_SELECTOR,"#sk-layout > div > div > section > div.ant-pro-layout-container > main > div > div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost > div.ant-page-header-content > div > div > div > div > div > div.avatar___3ZBop > span > img") if avatar.is_displayed(): print("头像元素渲染成功!") else: print("头像元素未正常显示!") # 测试用户名 username = self.driver.find_element(By.CSS_SELECTOR,"#sk-layout > div > div > section > div.ant-pro-layout-container > main > div > div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost > div.ant-page-header-content > div > div > div > div > div > div.content___1eLtZ > div.contentTitle___Yu-cR") display_name = username.text.split(",")[1].strip() if display_name == KingCramDriver.get_name(): print(f"用户名匹配成功!当前登录用户:{display_name}") else: print(f"用户名匹配失败!页面显示{display_name},预期{KingCramDriver.get_name()}") # ====================== 问卷数/考试数部分展示 ====================== def statDataShowTest(self): Dnumber = self.driver.find_element(By.CSS_SELECTOR,"#sk-layout > div > div > section > div.ant-pro-layout-container > main > div > div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost > div.ant-page-header-content > div > div > div > div > div > div.extraContent___3rMo7 > div:nth-child(1) > div > div.ant-statistic-title").text assert Dnumber == "问卷数" Tnumber = self.driver.find_element(By.CSS_SELECTOR,"#sk-layout > div > div > section > div.ant-pro-layout-container > main > div > div.ant-page-header.ant-pro-page-container-warp-page-header.ant-pro-page-container-warp-page-header.ant-page-header-has-breadcrumb.ant-page-header-ghost > div.ant-page-header-content > div > div > div > div > div > div.extraContent___3rMo7 > div:nth-child(2) > div > div.ant-statistic-title").text assert Tnumber == "考试数" # ====================== “我的考试”模块 ====================== def myExamListShowTest(self): # 测试词条模块 self.driver.find_element(By.CSS_SELECTOR,"#rc-tabs-0-panel-exam > div > div > div > div.ant-table-wrapper > div > div > div > div > div > table > thead > tr > th:nth-child(1)") self.driver.find_element(By.CSS_SELECTOR,"#rc-tabs-0-panel-exam > div > div > div > div.ant-table-wrapper > div > div > div > div > div > table > thead > tr > th:nth-child(2)") self.driver.find_element(By.CSS_SELECTOR,"#rc-tabs-0-panel-exam > div > div > div > div.ant-table-wrapper > div > div > div > div > div > table > thead > tr > th:nth-child(3)") self.driver.find_element(By.CSS_SELECTOR,"#rc-tabs-0-panel-exam > div > div > div > div.ant-table-wrapper > div > div > div > div > div > table > thead > tr > th:nth-child(4)") self.driver.find_element(By.CSS_SELECTOR,"#rc-tabs-0-panel-exam > div > div > div > div.ant-pro-table-list-toolbar > div > div.ant-space.ant-space-horizontal.ant-space-align-center.ant-pro-table-list-toolbar-right > div > div > div:nth-child(1) > div > span > span > svg").click() # ”密度”词条测试 self.driver.find_element(By.CSS_SELECTOR,"#rc-tabs-0-panel-exam > div > div > div > div.ant-pro-table-list-toolbar > div > div.ant-space.ant-space-horizontal.ant-space-align-center.ant-pro-table-list-toolbar-right > div > div > div:nth-child(2) > div > span > span > svg").click() compact = self.driver.find_element(By.XPATH, '//span[text()="紧凑"]') self.driver.execute_script("arguments[0].click();", compact) time.sleep(2) # 测试“设置列” self.driver.find_element(By.CSS_SELECTOR,"#rc-tabs-0-panel-exam > div > div > div > div.ant-pro-table-list-toolbar > div > div.ant-space.ant-space-horizontal.ant-space-align-center.ant-pro-table-list-toolbar-right > div > div > div:nth-child(3) > div > span > svg").click() # 将“考试名称“列清除 # 为什么复选框点击要改成 JS 点击 checkbox_list = self.driver.find_elements(By.CSS_SELECTOR, ".ant-popover span.ant-tree-checkbox-inner") start_time_box = checkbox_list[1] self.driver.execute_script("arguments[0].click();", start_time_box) time.sleep(2) KingCramDriver.getScreeShot() # =================================================================== # 这里"我的问卷""问卷记录""考试记录"测试内容和"我的考试"高度相似 # 所以仅测试了"我的考试"一个模块 # =================================================================== # 等待元素通用方法,替换原生find_element,解决元素加载超时 # 等待点击 def wait_click(self,locator,timeout = 10): ele = WebDriverWait(self.driver,timeout).until( EC.element_to_be_clickable(locator) ) ele.click() return ele # 等待输入 def wait_input(self, locator, text, timeout=10): # 每次都重新找元素,彻底杜绝 Stale ele = WebDriverWait(self.driver, timeout).until( lambda d: d.find_element(*locator) ) # 富文本必须用 JS 输入!!! self.driver.execute_script("arguments[0].innerText = arguments[1];", ele, text) return ele # ====================== “快速开始 / 便捷导航”模块 ====================== def quickStartNavShowTest(self): # -----------------------创建问卷词条相关----------------------------------- self.wait_click((By.CSS_SELECTOR,"#sk-layout > div > div > section > div.ant-pro-layout-container > main > div > div.ant-pro-grid-content > div > div > div > div.ant-col.ant-col-xs-24.ant-col-sm-24.ant-col-md-24.ant-col-lg-24.ant-col-xl-8 > div > div.ant-card-body > div > a:nth-child(1)")) # ==================题目部分======================== self.wait_click((By.XPATH,'//*[@id="editor"]/div[1]/div[1]/div[1]')) # 添加题型-添加单选题 self.wait_click((By.XPATH, '//div[contains(@id,"rc-tabs") and contains(@id,"panel-1")]//dl[1]//dd/div')) # 1. 输入题目题干 self.wait_input((By.XPATH, '//*[@id="editorContent"]/div/div/div[2]/div/div[1]/div/div[1]/div[1]/div[2]/div/pre/div[1]/p'),"自动化测试单选题题干") # 2. 修改选项1 self.wait_input((By.XPATH,'//*[@id="editorContent"]/div/div/div[2]/div/div[1]/div/div[1]/div[3]/div/div/div[1]/div/div/div[1]/div[1]'),"自动化测试选项A") # 3. 修改选项2 self.wait_input((By.XPATH,'//*[@id="editorContent"]/div/div/div[2]/div/div[1]/div/div[1]/div[3]/div/div/div[2]/div/div/div[1]/div[1]'),"自动化测试选项B") # 4. 单个新增选项 self.wait_click((By.XPATH, '//*[@id="editorContent"]/div/div/div[2]/div/div[1]/div/div[1]/div[4]/div/a[1]')) self.wait_input((By.XPATH,'//*[@id="editorContent"]/div/div/div[2]/div/div[1]/div/div[1]/div[3]/div/div/div[3]/div/div/div[1]/div[1]'),"自动化测试选项C") # 5. 批量添加选项 # 定位弹窗文本域,输入多行选项(换行分隔,一行一个选项) self.wait_click((By.XPATH, '//*[@id="editorContent"]/div/div/div[2]/div/div[1]/div/div[1]/div[4]/div/a[2]')) batch_textarea = WebDriverWait(self.driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR,"#editorContent > div > div > div:nth-child(2) > div > div:nth-child(1) > div > div:nth-child(3) > div > div > div > div.ant-popover-inner > div > div.ant-popover-message > div > div > textarea"))) batch_textarea.clear() # 批量写入3个选项,换行分隔 batch_textarea.send_keys("批量选项1\n批量选项2\n批量选项3") time.sleep(2) # 点击确认添加 self.wait_click((By.XPATH,'//*[@id="editorContent"]/div/div/div[2]/div/div[1]/div/div[3]/div/div/div/div[2]/div/div[2]/button[2]/span')) time.sleep(2) KingCramDriver.getScreeShot() # ==================题库部分======================== # 查看题库 self.wait_click((By.XPATH,'//*[@id="editor"]/div[1]/div[2]/div/div/div[1]/div[1]/div/div[2]')) time.sleep(2) KingCramDriver.getScreeShot() # 查看大纲 self.wait_click((By.XPATH,'//*[@id="editor"]/div[1]/div[2]/div/div/div[1]/div[1]/div/div[3]')) time.sleep(2) KingCramDriver.getScreeShot() # ==================外观部分======================== self.wait_click((By.XPATH,'//*[@id="editor"]/div[1]/div[1]/div[2]')) # 背景图 self.wait_click((By.XPATH,'//*[@id="editor"]/div[1]/div[2]/div/div/div[1]/div[1]/div/div[1]')) # 点击背景图面板 self.wait_click((By.CSS_SELECTOR, '[id*="panel-bgi"] > div > div'), 15) time.sleep(2) # 关闭弹窗 close_btn = self.driver.find_element(By.CSS_SELECTOR, 'button[aria-label*="Close"]') self.driver.execute_script("arguments[0].click();", close_btn) time.sleep(2) # 页眉图和背景图测试内容相似 # 省略页眉图测试 # ==================逻辑部分======================== self.wait_click((By.XPATH,'//*[@id="editor"]/div[1]/div/div[3]')) time.sleep(2) t = self.driver.find_element(By.XPATH,'//*[@id="editorContent"]/div/div[2]/div/div[2]/div/div').text if t == "暂无逻辑": self.wait_click((By.XPATH,'//*[@id="editorContent"]/div/div[2]/div/div[2]/div/button')) time.sleep(2) else: self.wait_click((By.XPATH,'//*[@id="editorContent"]/div/div[1]/div/button')) time.sleep(2) self.wait_click((By.XPATH, '//*[@id="editorContent"]/div/div[1]/div/button')) KingCramDriver.getScreeShot() # ----------------------- 创建考试词条相关----------------------------------- # 创建考试部分和创建问卷内容相似 # 测试省略 self.driver.back()

具体代码链接:https://gitee.com/dwaekkiyo/king-cram-atuo-test/tree/main/tests

所有模块测试用例通过 RunTest.py 批量执行,覆盖登录、注册、首页、练习、项目、题库、系统管理全业务流程

2.4 自动化执行过程中发现的业务缺陷
  1. 我的项目模块:项目展示列表页面渲染加载耗时过长,无数据场景接口响应耗时接近 4 分钟,压测报 Socket closed 连接断开
  2. 我的练习 - 测试题库模块:①测试题库标签在自动化环境中无法正常点击;②点击【开始练习】后页面丢失标签状态,自动切回「我的练习」列表页
  3. 全局页面返回逻辑缺陷:所有编辑器页面执行返回操作后,直接跳转至系统首页,无法回到上一级编辑页面

(二)性能测试

1. 模拟并发访问项目事务各页面

10 个接口,每个接口 150 样本

此时可以看出:

  • 总请求 10*150=1500 条,错误率 0%,无接口报错,功能层面稳定
  • 99% 请求都接近 5.8 秒,整体响应偏慢,存在明显性能瓶颈,尤其是我的题库界面、我的练习存在严重耗时
  • 响应时间长,吞吐量小或相对稳定,可能系统达到了性能瓶颈。
  • 响应时间短,吞吐量大,性能越好

通过Jmeter生成的报告可以得出:

  • 150个接口功能稳定性已修复(无报错),但核心页面性能存在硬伤,两个高频页面几乎无合格响应请求;系统整体延迟偏高、并发承载能力不足,若直接提升并发至 200,会再次出现超时、响应雪崩问题,必须优先优化题库、练习列表接口

2. 高并发下系统产生的问题观测与验证

  • 当单样本数量从150增加至200时,仅登录接口报错,错误类型为套接字读取超时,200 次请求里 34 次失败,登录错误率 17%
  • 如果直接上 300 并发,会出现大面积接口 Socket 超时,系统基本不可用
  • 证明150 单接口并发已是当前系统稳定临界值,不做优化无法承载更多用户并发!

3. 我的项目模块页面请求超长耗时问题验证

  • 低压力少量线程场景:接口可以正常返回完整业务 JSON(包含全部问卷、题目、选项嵌套数据),但单次请求耗时长达近 4 分钟才能加载完成
  • 高并发加压场景:当并发量提升、大量请求同时打向该接口时,服务端无法在超时窗口内完成查询处理,TCP 连接被强制断开,抛出java.net.SocketException:Socket closed ,请求直接失败,无法拿到返回数据

四、遗留风险

  1. 性能承载短板:系统稳定并发上限仅 150,低并发下「我的项目列表」请求耗时近 4 分钟;并发超 150 易出现 Socket 连接断开,200 并发登录报错率 17%,300 并发系统基本不可用。题库、练习、项目列表高频接口缺少索引、分页、缓存,大数据查询阻塞线程,存在响应雪崩线上故障风险。
  2. 自动化维护成本高:脚本依靠 DOM 定位,前端页面重构后会导致用例失效,需同步修改选择器;未接入 CI 流水线,无法自动定时执行压测、冒烟回归。
  3. 前端交互缺陷遗留:页面跳转丢失标签状态、练习标签点击失效等交互问题未修复,持续影响用户操作体验

五、测试结果评估

自动化覆盖全业务模块,可支撑迭代冒烟回归,同步发现交互、性能类缺陷并提报优化;JMeter 压测证实系统功能可用,但核心页面存在致命性能瓶颈,高频列表接口整体延迟偏高,直接上线会出现页面长时间加载、高并发大面积超时问题

建议优先完成慢 SQL、索引、缓存等性能优化后再放量上线;线上持续监控接口耗时、服务器资源、报错率,持续迭代优化交互与加载性能

http://www.jsqmd.com/news/1091948/

相关文章:

  • MSP430X寄存器操作与寻址模式深度解析:嵌入式底层开发核心机制
  • AI辅助渗透测试实战:基于Gemini CLI的提示词设计与自动化应用
  • 零基础 Vibe Coding 教程 AI 编程的完整流程 33-36
  • [智能体-586]:OpenClaw(小龙虾) Hermes Agent 全量注意事项与潜在坑
  • Go语言的sync.RWMutex中的使用内存屏障
  • CDS API终极指南:3步解锁全球气象数据的Python实战教程
  • ChatGPT Plus / Pro 使用心得整理:真正拉开差距的,不是版本,而是用法
  • 通过列表生成式构建一个生成器
  • [智能体-587]:node.js概述以及其在OpenClaw等智能体的能力边界,控制本地系统中的作用与意义
  • 从 0 开始学习 AI 测试 - 从接口测试来教你如何用 AI 来生成自动化测试代码
  • 实操-大白菜的五个实操
  • Java毕设选题推荐:基于 JavaWeb 的油田耗材物资台账管理系统 油田生产物资库存统计与调度管理系统【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 3分钟掌握AI视频剪辑:零门槛智能剪辑工具FunClip完全指南
  • 数据库工程:生产环境索引策略落地全示例‌
  • # 程序员为什么越来越离不开 ChatGPT Plus / Pro?不是偷懒,而是减少无效消耗
  • OpenCode 的核心设计:主 Agent 与子 Agent 的分层架构
  • Mac Mouse Fix终极指南:让你的普通鼠标在macOS上实现专业级体验
  • 1W 工业 DC-DC 隔离模块硬件选型技术解析丨A2415XT-1WR3 和钡特电源 DB1-24D15XT 优质稳定供应丨国产丨24V转±15V丨贴片SMD封装
  • 安卓手机厂商宣布部分产品调价
  • MSPM0 LFSS低功耗子系统:RTC、看门狗与篡改检测的实战配置
  • 【ChatGPT提示词黄金公式】:20年AI工程师亲测有效的7类高响应率提示结构(附可复用模板库)
  • AI时代意图经济的概念、GEO框架与内容营销底层逻辑,AI新媒体营销专家培训讲师唐兴通分享
  • 文科背景想懂技术商业管理-国内硕士转型路径与交大MTT五力培养
  • 写了5年代码,你还有多少竞争力?
  • 暗黑破坏神2存档编辑器:5分钟掌握免费D2/D2R游戏存档修改
  • 【AIGC生产环境必修课】:ChatGPT结构化提示词的4阶验证体系——错误率下降67%的实测数据支撑
  • 接口测试全流程实战:从设计到自动化,构建高效质量保障体系
  • Windows 10也能原生运行Android应用?WSA-Windows-10逆向移植项目终极实战指南
  • ChatGPT Plus退订≠权限清零!(企业管理员必看):团队License回收机制、共享工作区访问残留、API Key有效期延长策略及审计日志导出路径
  • C# 内存安全性的重大演进:重新定义 unsafe 关键字