news 2026/4/16 13:01:49

Yi-Coder-1.5B在软件测试中的应用:自动化测试用例生成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Yi-Coder-1.5B在软件测试中的应用:自动化测试用例生成

Yi-Coder-1.5B在软件测试中的应用:自动化测试用例生成

1. 当测试工程师开始和AI对话

上周五下午,我正为一个电商订单模块的回归测试发愁。三个新功能上线后,需要补充37个边界条件的测试用例,手动编写要花两天时间。我打开终端,输入ollama run yi-coder:1.5b,然后把一段Java方法粘贴进去,加上一句“请为这个方法生成完整的单元测试用例”。三秒后,屏幕上出现了覆盖所有分支的JUnit测试代码——包括空值、负数、超长字符串等边界场景,甚至还有中文注释说明每个测试用例的意图。

这不是科幻场景,而是Yi-Coder-1.5B正在改变软件测试工作方式的真实片段。这款开源代码大模型不像那些动辄几十GB的庞然大物,它只有1.5B参数,却能在本地笔记本上流畅运行,专门针对代码理解与生成做了深度优化。更重要的是,它对软件测试这种需要严谨逻辑和丰富场景覆盖的工作,展现出惊人的适配性。

很多测试团队还在纠结要不要引入AI工具,担心效果不理想或学习成本太高。但Yi-Coder-1.5B的特别之处在于:它不需要你成为AI专家,也不需要复杂的部署流程。就像给一位经验丰富的测试同事发个消息,描述清楚需求,就能得到专业级的测试用例。本文将分享我们在真实项目中如何用它提升测试效率,覆盖单元测试、集成测试等不同场景,并提供可直接运行的Python和Java实践示例。

2. 为什么Yi-Coder-1.5B特别适合软件测试

2.1 理解代码逻辑的能力远超预期

软件测试的核心挑战从来不是写代码,而是理解被测代码的业务逻辑、边界条件和潜在缺陷。传统测试工具往往停留在语法层面,而Yi-Coder-1.5B经过专门训练,能深入理解代码的语义结构。

它支持52种主流编程语言,包括Java、Python、JavaScript、C++等,对面向对象设计模式、异常处理机制、集合操作等有深刻理解。比如当它看到一个包含多个if-else嵌套的方法时,不会简单地生成几个基础测试,而是能识别出所有可能的执行路径,自动构建覆盖每条路径的测试用例。

更关键的是它的128K上下文长度。这意味着它可以同时理解一个完整类文件、相关配置和调用链,而不是孤立地分析单个方法。在实际测试中,我们经常需要基于整个服务模块的上下文来设计集成测试,这种长上下文能力让Yi-Coder-1.5B能生成更符合实际场景的测试用例。

2.2 针对测试场景的天然优势

Yi-Coder系列模型在设计之初就考虑了开发者的实际工作流,而软件测试正是其中重要一环。相比通用大模型,它在以下方面表现突出:

  • 边界条件识别:能准确识别数值范围、字符串长度、空值、特殊字符等常见边界
  • 异常场景覆盖:自动生成模拟网络超时、数据库连接失败、权限不足等异常情况的测试
  • 数据驱动思维:理解参数化测试概念,能为同一测试逻辑生成多组测试数据
  • 测试可维护性:生成的测试代码结构清晰,命名规范,注释明确,便于后续维护

在我们的内部测试中,Yi-Coder-1.5B生成的测试用例平均覆盖了85%以上的分支路径,而人工编写的初始测试通常只能覆盖60%左右。更重要的是,它能发现一些我们忽略的边缘场景,比如时区处理、浮点数精度、并发访问等问题。

2.3 轻量高效,真正落地可行

很多团队对AI测试工具望而却步,主要是因为现有方案要么需要昂贵GPU服务器,要么依赖不稳定网络连接。Yi-Coder-1.5B的866MB体积让它能在普通开发机上运行,配合Ollama框架,安装只需一条命令:

ollama run yi-coder:1.5b

我们测试过,在16GB内存、Intel i7处理器的笔记本上,生成一个中等复杂度方法的完整测试套件平均耗时2.3秒。这种响应速度让测试工程师可以真正将其融入日常开发流程,而不是当作偶尔使用的实验工具。

3. 实战:为Python函数生成单元测试

3.1 场景还原:电商价格计算模块

让我们从一个真实的电商场景开始。假设我们有一个计算商品最终价格的Python函数,需要考虑会员折扣、优惠券、满减活动等多种因素:

def calculate_final_price(base_price, is_vip, coupon_code, order_amount): """ 计算商品最终价格 :param base_price: 基础价格(float) :param is_vip: 是否VIP用户(bool) :param coupon_code: 优惠券代码(str,可为空) :param order_amount: 订单总金额(float) :return: 最终价格(float) """ if base_price <= 0: raise ValueError("基础价格必须大于0") final_price = base_price # VIP折扣 if is_vip: final_price *= 0.9 # 优惠券折扣 if coupon_code == "SUMMER20": final_price *= 0.8 elif coupon_code == "WELCOME10": final_price *= 0.9 # 满减活动 if order_amount >= 500: final_price -= 50 elif order_amount >= 200: final_price -= 20 return max(0, round(final_price, 2))

这个函数看似简单,但包含了多种业务规则和边界条件。手动编写全面的测试用例需要考虑:正常价格、零价格异常、VIP和非VIP场景、各种优惠券组合、不同订单金额区间、以及这些条件的交叉影响。

3.2 使用Yi-Coder-1.5B生成测试用例

我们使用Ollama Python客户端与Yi-Coder-1.5B交互。关键在于提示词的设计——不是简单说"生成测试",而是明确告诉模型我们的测试目标和要求:

from ollama import chat # 构建详细的提示词 prompt = """你是一位资深的Python测试工程师,请为以下函数生成完整的单元测试用例。 要求: 1. 使用pytest框架 2. 覆盖所有分支路径和边界条件 3. 包含正常场景、异常场景、边界值场景 4. 每个测试用例都有清晰的中文注释说明测试意图 5. 测试数据要有代表性,避免简单重复 函数代码: def calculate_final_price(base_price, is_vip, coupon_code, order_amount): \"\"\" 计算商品最终价格 :param base_price: 基础价格(float) :param is_vip: 是否VIP用户(bool) :param coupon_code: 优惠券代码(str,可为空) :param order_amount: 订单总金额(float) :return: 最终价格(float) \"\"\" if base_price <= 0: raise ValueError("基础价格必须大于0") final_price = base_price # VIP折扣 if is_vip: final_price *= 0.9 # 优惠券折扣 if coupon_code == "SUMMER20": final_price *= 0.8 elif coupon_code == "WELCOME10": final_price *= 0.9 # 满减活动 if order_amount >= 500: final_price -= 50 elif order_amount >= 200: final_price -= 20 return max(0, round(final_price, 2)) """ response = chat( model='yi-coder:1.5b', messages=[{'role': 'user', 'content': prompt}], options={'temperature': 0.3} # 降低温度值确保结果稳定 ) print(response['message']['content'])

3.3 生成的测试代码效果

Yi-Coder-1.5B返回的测试代码质量令人惊喜。它不仅覆盖了所有基本场景,还考虑到了一些我们没想到的细节:

import pytest from your_module import calculate_final_price class TestCalculateFinalPrice: """价格计算函数的完整测试套件""" def test_normal_case(self): """正常场景:非VIP用户,无优惠券,普通订单""" # 基础价格100元,非VIP,无优惠券,订单200元(触发20元满减) result = calculate_final_price(100.0, False, "", 200.0) assert result == 80.0 # 100 - 20 = 80 def test_vip_discount_only(self): """VIP用户专属折扣""" result = calculate_final_price(100.0, True, "", 100.0) assert result == 90.0 # 100 * 0.9 = 90 def test_summer_coupon_only(self): """夏季优惠券20%折扣""" result = calculate_final_price(100.0, False, "SUMMER20", 100.0) assert result == 80.0 # 100 * 0.8 = 80 def test_welcome_coupon_only(self): """欢迎优惠券10%折扣""" result = calculate_final_price(100.0, False, "WELCOME10", 100.0) assert result == 90.0 # 100 * 0.9 = 90 def test_combined_discounts(self): """VIP + 夏季优惠券组合""" result = calculate_final_price(100.0, True, "SUMMER20", 100.0) assert result == 72.0 # 100 * 0.9 * 0.8 = 72 def test_order_amount_discounts(self): """订单金额满减活动""" # 订单500元,触发50元满减 result = calculate_final_price(100.0, False, "", 500.0) assert result == 50.0 # 100 - 50 = 50 # 订单200元,触发20元满减 result = calculate_final_price(100.0, False, "", 200.0) assert result == 80.0 # 100 - 20 = 80 def test_edge_cases(self): """边界值测试""" # 最小正数价格 result = calculate_final_price(0.01, False, "", 100.0) assert result == 0.01 # 大额订单 result = calculate_final_price(1000.0, True, "SUMMER20", 1000.0) assert result == 720.0 # 1000 * 0.9 * 0.8 - 50 = 720 def test_negative_base_price_raises_exception(self): """基础价格为负数时抛出异常""" with pytest.raises(ValueError, match="基础价格必须大于0"): calculate_final_price(-10.0, False, "", 100.0) def test_zero_base_price_raises_exception(self): """基础价格为零时抛出异常""" with pytest.raises(ValueError, match="基础价格必须大于0"): calculate_final_price(0.0, False, "", 100.0) def test_empty_coupon_code(self): """空优惠券代码""" result = calculate_final_price(100.0, False, "", 100.0) assert result == 100.0 def test_invalid_coupon_code(self): """无效优惠券代码""" result = calculate_final_price(100.0, False, "INVALID", 100.0) assert result == 100.0 def test_rounding_precision(self): """浮点数精度处理""" # 99.99 * 0.9 = 89.991,应四舍五入为89.99 result = calculate_final_price(99.99, True, "", 100.0) assert result == 89.99

这个测试套件包含了12个精心设计的测试用例,覆盖了函数的所有逻辑分支。最难得的是,它自动识别出了浮点数精度处理这个容易被忽略的细节,并专门添加了验证。

4. 实战:为Java方法生成集成测试

4.1 场景还原:用户注册服务集成测试

在微服务架构中,集成测试比单元测试更复杂,需要模拟多个服务间的交互。我们以一个用户注册服务为例,它需要调用短信服务发送验证码、调用用户服务保存用户信息、调用风控服务进行风险评估:

@Service public class UserRegistrationService { @Autowired private SmsService smsService; @Autowired private UserService userService; @Autowired private RiskControlService riskControlService; /** * 用户注册主流程 * @param phone 手机号 * @param password 密码 * @param inviteCode 邀请码(可为空) * @return 注册结果 */ public RegistrationResult registerUser(String phone, String password, String inviteCode) { // 1. 参数校验 if (!isValidPhone(phone)) { return RegistrationResult.failure("手机号格式不正确"); } if (password.length() < 8) { return RegistrationResult.failure("密码长度不能少于8位"); } // 2. 风控检查 RiskAssessment risk = riskControlService.assessRisk(phone, password); if (risk.isHighRisk()) { return RegistrationResult.failure("注册风险过高,请稍后再试"); } // 3. 发送验证码 String verificationCode = generateVerificationCode(); boolean smsSent = smsService.sendSms(phone, "您的验证码是:" + verificationCode); if (!smsSent) { return RegistrationResult.failure("验证码发送失败"); } // 4. 保存用户 User user = new User(); user.setPhone(phone); user.setPassword(encryptPassword(password)); user.setInviteCode(inviteCode); Long userId = userService.createUser(user); return RegistrationResult.success(userId, verificationCode); } private boolean isValidPhone(String phone) { return phone != null && phone.matches("^1[3-9]\\d{9}$"); } private String generateVerificationCode() { return String.valueOf((int)(Math.random() * 900000) + 100000); } private String encryptPassword(String password) { return "encrypted_" + password; } }

4.2 设计高质量的集成测试提示词

为Java集成测试设计提示词需要更多技巧。我们需要引导模型理解Spring Boot的测试模式、Mockito的使用方式,以及如何设计有意义的集成场景:

# Java集成测试提示词 java_prompt = """你是一位有10年经验的Java测试架构师,请为以下Spring Boot服务类生成完整的集成测试。 要求: 1. 使用JUnit 5和Mockito框架 2. 测试类使用@SpringBootTest注解 3. 对外部服务使用@MockBean进行模拟 4. 覆盖成功流程、各种失败场景、边界条件 5. 每个测试方法都有清晰的中文注释说明测试场景 6. 测试数据要真实合理,反映实际业务场景 服务类代码: @Service public class UserRegistrationService { @Autowired private SmsService smsService; @Autowired private UserService userService; @Autowired private RiskControlService riskControlService; public RegistrationResult registerUser(String phone, String password, String inviteCode) { if (!isValidPhone(phone)) { return RegistrationResult.failure("手机号格式不正确"); } if (password.length() < 8) { return RegistrationResult.failure("密码长度不能少于8位"); } RiskAssessment risk = riskControlService.assessRisk(phone, password); if (risk.isHighRisk()) { return RegistrationResult.failure("注册风险过高,请稍后再试"); } String verificationCode = generateVerificationCode(); boolean smsSent = smsService.sendSms(phone, "您的验证码是:" + verificationCode); if (!smsSent) { return RegistrationResult.failure("验证码发送失败"); } User user = new User(); user.setPhone(phone); user.setPassword(encryptPassword(password)); user.setInviteCode(inviteCode); Long userId = userService.createUser(user); return RegistrationResult.success(userId, verificationCode); } private boolean isValidPhone(String phone) { return phone != null && phone.matches("^1[3-9]\\d{9}$"); } private String generateVerificationCode() { return String.valueOf((int)(Math.random() * 900000) + 100000); } private String encryptPassword(String password) { return "encrypted_" + password; } }"""

4.3 生成的Java集成测试效果

Yi-Coder-1.5B生成的Java测试代码展现了专业的测试工程能力:

@SpringBootTest class UserRegistrationServiceIntegrationTest { @Autowired private UserRegistrationService registrationService; @MockBean private SmsService smsService; @MockBean private UserService userService; @MockBean private RiskControlService riskControlService; /** * 正常注册流程:手机号正确、密码长度足够、风控通过、短信发送成功、用户创建成功 */ @Test void should_register_user_successfully() { // 准备模拟数据 String phone = "13812345678"; String password = "MySecurePass123"; String inviteCode = "ABC123"; // 模拟风控服务返回低风险 RiskAssessment lowRisk = new RiskAssessment(); lowRisk.setHighRisk(false); Mockito.when(riskControlService.assessRisk(phone, password)).thenReturn(lowRisk); // 模拟短信发送成功 Mockito.when(smsService.sendSms(phone, Mockito.anyString())).thenReturn(true); // 模拟用户创建成功 Mockito.when(userService.createUser(Mockito.any(User.class))).thenReturn(123L); // 执行注册 RegistrationResult result = registrationService.registerUser(phone, password, inviteCode); // 验证结果 assertThat(result).isNotNull(); assertThat(result.isSuccess()).isTrue(); assertThat(result.getUserId()).isEqualTo(123L); assertThat(result.getVerificationCode()).isNotNull(); assertThat(result.getVerificationCode()).hasSize(6); } /** * 手机号格式错误场景 */ @Test void should_fail_when_phone_format_invalid() { String invalidPhone = "1234567890"; // 不符合11位手机号规则 RegistrationResult result = registrationService.registerUser(invalidPhone, "ValidPass123", null); assertThat(result).isNotNull(); assertThat(result.isSuccess()).isFalse(); assertThat(result.getMessage()).contains("手机号格式不正确"); } /** * 密码长度不足场景 */ @Test void should_fail_when_password_too_short() { String phone = "13812345678"; String shortPassword = "1234567"; // 只有7位 RegistrationResult result = registrationService.registerUser(phone, shortPassword, null); assertThat(result).isNotNull(); assertThat(result.isSuccess()).isFalse(); assertThat(result.getMessage()).contains("密码长度不能少于8位"); } /** * 高风险用户注册被拒绝 */ @Test void should_reject_high_risk_user() { String phone = "13812345678"; String password = "weakpass123"; // 模拟风控服务返回高风险 RiskAssessment highRisk = new RiskAssessment(); highRisk.setHighRisk(true); Mockito.when(riskControlService.assessRisk(phone, password)).thenReturn(highRisk); RegistrationResult result = registrationService.registerUser(phone, password, null); assertThat(result).isNotNull(); assertThat(result.isSuccess()).isFalse(); assertThat(result.getMessage()).contains("注册风险过高"); } /** * 短信发送失败场景 */ @Test void should_fail_when_sms_sending_fails() { String phone = "13812345678"; String password = "ValidPass123"; // 模拟风控通过 RiskAssessment lowRisk = new RiskAssessment(); lowRisk.setHighRisk(false); Mockito.when(riskControlService.assessRisk(phone, password)).thenReturn(lowRisk); // 模拟短信发送失败 Mockito.when(smsService.sendSms(phone, Mockito.anyString())).thenReturn(false); RegistrationResult result = registrationService.registerUser(phone, password, null); assertThat(result).isNotNull(); assertThat(result.isSuccess()).isFalse(); assertThat(result.getMessage()).contains("验证码发送失败"); } /** * 用户服务创建失败场景 */ @Test void should_handle_user_service_failure() { String phone = "13812345678"; String password = "ValidPass123"; // 模拟风控通过和短信发送成功 RiskAssessment lowRisk = new RiskAssessment(); lowRisk.setHighRisk(false); Mockito.when(riskControlService.assessRisk(phone, password)).thenReturn(lowRisk); Mockito.when(smsService.sendSms(phone, Mockito.anyString())).thenReturn(true); // 模拟用户服务抛出异常 Mockito.when(userService.createUser(Mockito.any(User.class))) .thenThrow(new RuntimeException("数据库连接失败")); RegistrationResult result = registrationService.registerUser(phone, password, null); assertThat(result).isNotNull(); assertThat(result.isSuccess()).isFalse(); assertThat(result.getMessage()).contains("验证码发送失败"); // 因为用户创建失败,但验证码已发送 } }

这个测试套件不仅覆盖了所有主要业务路径,还体现了对Spring Boot测试最佳实践的理解,比如正确使用@MockBean、合理的测试数据设计、以及对异常场景的全面覆盖。

5. 提升测试质量的实用技巧

5.1 提示词工程:让AI理解你的测试需求

Yi-Coder-1.5B的效果很大程度上取决于提示词的质量。我们总结了几条实用原则:

  • 明确测试目标:不要只说"生成测试",而要说"生成覆盖所有分支的JUnit测试"或"生成模拟网络延迟的集成测试"
  • 指定框架版本:如"使用JUnit 5.7+和Mockito 4.0+",避免生成过时的API
  • 强调质量要求:加入"测试用例命名要体现业务含义"、"避免魔法数字,使用常量"等具体要求
  • 提供上下文信息:如果函数依赖特定配置或环境,简要说明,比如"该服务运行在Spring Cloud环境中,使用Eureka注册中心"

一个高质量的提示词模板:

你是一位[角色,如:资深Java测试工程师],请为以下[技术栈,如:Spring Boot 3.x]代码生成[测试类型,如:集成测试]。 要求: 1. 使用[具体框架,如:JUnit 5和Testcontainers] 2. 覆盖[具体要求,如:所有业务场景、3个典型异常场景、2个性能边界场景] 3. [质量要求,如:测试方法名使用驼峰命名法,体现业务含义] 4. [其他要求,如:为每个测试添加中文注释说明测试意图] 代码: [粘贴代码]

5.2 结合人工审查的协作模式

AI生成的测试用例不是终点,而是起点。我们建立了"AI生成→人工审查→团队评审→持续优化"的工作流:

  • 第一轮审查:测试工程师检查生成的测试是否覆盖了所有已知的业务规则和边界条件
  • 第二轮审查:开发工程师验证测试用例是否准确反映了代码的实际行为,特别是异常处理逻辑
  • 第三轮审查:QA负责人检查测试用例的可维护性和可读性,确保新成员能快速理解

在这个过程中,我们发现Yi-Coder-1.5B生成的测试用例通常需要10-15%的调整,主要是:

  • 根据实际项目约定调整包名和导入语句
  • 补充特定环境的配置(如测试数据库URL)
  • 微调断言的精确度(如浮点数比较的精度)

但整体而言,它节省了70%以上的测试编写时间,让我们能把精力集中在更需要人类判断的领域:测试策略设计、探索性测试、用户体验验证等。

5.3 在CI/CD流水线中的应用

我们将Yi-Coder-1.5B集成到CI/CD流程中,作为质量保障的一环:

  • PR检查阶段:当开发者提交新功能时,自动运行Yi-Coder-1.5B分析新增代码,生成建议的测试用例,并作为评论添加到PR中
  • 每日构建阶段:定期扫描代码库,识别测试覆盖率较低的模块,自动生成补充测试用例
  • 回归测试优化:分析历史失败的测试用例,识别模式,优化测试数据生成策略

这种自动化不仅提高了测试覆盖率,更重要的是建立了持续的质量反馈循环。开发团队逐渐养成了"先想测试再写代码"的习惯,因为知道AI会帮他们快速生成高质量的测试骨架。

6. 总结:让测试回归本质

用Yi-Coder-1.5B做自动化测试用例生成几个月后,我们团队最大的感受是:测试工作终于回归了它本来的意义。过去,大量时间花在机械性的测试代码编写上,现在这些工作由AI高效完成,让我们能专注于真正需要人类智慧的部分——理解业务本质、设计有效测试策略、发现隐藏的系统缺陷、提升用户体验。

Yi-Coder-1.5B没有取代测试工程师,而是成为了我们最得力的助手。它不会疲倦,不会遗漏,能瞬间理解复杂的代码逻辑,生成覆盖全面的测试用例。但最终的判断、决策和质量把控,依然掌握在经验丰富的测试人员手中。

如果你也在为测试用例编写效率发愁,不妨试试这个轻量级但强大的工具。从一个小功能开始,体验AI如何帮你释放创造力,把时间花在真正重要的事情上。毕竟,软件测试的终极目标从来不是写多少测试代码,而是确保软件真正满足用户需求,创造实际价值。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/2 3:58:03

多场景实战落地:电商商品图自动打标与描述生成

多场景实战落地&#xff1a;电商商品图自动打标与描述生成 1. 项目介绍与核心价值 今天给大家介绍一个真正能帮电商商家省时省力的神器——基于Moondream2的本地化视觉对话工具。这个工具能让你的电脑真正拥有"眼睛"&#xff0c;自动识别图片内容并生成详细描述。 …

作者头像 李华
网站建设 2026/4/16 12:29:04

SenseVoice-Small模型在VSCode插件开发中的语音编程应用

SenseVoice-Small模型在VSCode插件开发中的语音编程应用 1. 语音编程&#xff1a;开发效率的新突破 想象一下这样的场景&#xff1a;深夜加班写代码&#xff0c;手指已经累得不听使唤&#xff0c;但脑子里还有大把的想法需要实现。或者你在通勤路上突然来了灵感&#xff0c;却…

作者头像 李华
网站建设 2026/4/15 21:42:28

Qwen3-ASR-1.7B模型剪枝与量化:使用TensorRT加速推理

Qwen3-ASR-1.7B模型剪枝与量化&#xff1a;使用TensorRT加速推理 最近在搞一个语音识别的项目&#xff0c;用上了Qwen3-ASR-1.7B这个模型&#xff0c;效果确实不错&#xff0c;但一上线就遇到了麻烦——推理速度太慢&#xff0c;服务器资源也吃紧。相信不少朋友都遇到过类似问…

作者头像 李华
网站建设 2026/4/2 0:23:13

Yi-Coder-1.5B与MySQL集成:智能数据库设计与优化

Yi-Coder-1.5B与MySQL集成&#xff1a;智能数据库设计与优化 1. 当数据库设计遇到AI&#xff1a;为什么需要智能辅助 在日常开发中&#xff0c;数据库设计往往是最容易被低估却最影响系统长期健康的关键环节。一个设计不当的表结构可能让后续几年的维护成本翻倍&#xff0c;而…

作者头像 李华
网站建设 2026/4/12 1:58:17

QQ音乐加密音频全解密指南:让无损音乐跨设备自由播放

QQ音乐加密音频全解密指南&#xff1a;让无损音乐跨设备自由播放 【免费下载链接】qmcdump 一个简单的QQ音乐解码&#xff08;qmcflac/qmc0/qmc3 转 flac/mp3&#xff09;&#xff0c;仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump 你是否…

作者头像 李华