用LLM做测试驱动开发:有趣又高效的尝试

server/2025/1/19 1:31:52/

  每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领域的领跑者。点击订阅,与未来同行! 订阅:https://rengongzhineng.io/

最近和同事讨论Tabby时,有人提到AI自动补全代码的潜在危害,比如因LLM(大型语言模型)的不可靠性导致代码质量下降,甚至滋生“意大利面条”代码,把像DRY这样的传统开发原则扔得一干二净。但本文的作者对此持不同意见:如果可以有一个框架,既能整合AI工具,又能让代码变得更可靠,会怎么样?这个想法让人瞬间联想到测试驱动开发(TDD)这种方法,尤其是结合LLM时的潜力。


TDD + LLM:从理想到现实的融合

TDD的核心思路是先写出覆盖全面的单元测试,再根据测试来实现主程序。理论上,测试本身就像完整的规范,所有测试通过则说明程序是正确的。然而,TDD在实践中被许多人认为拖慢了开发速度,甚至可能一无所获。LLM的出现,从经济效益上改变了这种状况。

在传统开发中,作者经常依赖像GitHub Copilot这样的工具来辅助编码。这些工具擅长识别模式并补全代码,但对深入理解需求、编写完整模块常常力不从心。为了让LLM高效工作,作者总结了一些经验:提出清晰的需求说明、逐步提供必要上下文、控制模型的注意力范围等。同时,LLM在调试方面表现优异——给出原始报错信息,它往往能猜出问题所在。

然而,频繁的切换窗口、复制粘贴上下文成了主要障碍。于是,作者尝试通过自动化脚本来简化整个流程。


自动化的TDD:工作流详解

作者写了一个简单的事件循环来自动化测试驱动开发

  1. 定义需求与函数签名:第一步是向LLM提供明确的功能描述和函数签名,比如: go run main.go --spec '开发一个函数,输入一段长文本,识别并解析其中的IPv4、IPv6地址和CIDR块(这些可能夹杂在其他符号或文本之间),并将结果返回为列表' --sig 'func ParseCidrs(input string) ([]*net.IPNet, error)' 模型会生成初版实现和对应的单元测试。
  2. 沙箱验证:将生成的代码和测试放入沙箱目录,执行一系列工具(如go mod tidygo test)进行语法修复和单元测试。
  3. 迭代优化:如果初版测试失败,作者会将测试输出和相关代码反馈给模型,让其分析问题并修复代码。这一循环持续进行,直到所有测试通过。

通过这种方式,可以降低模型上下文的长度,节省成本,同时提高迭代效率。


模型的局限与对策

尽管方法有效,但也存在局限。例如,模型可能生成质量不高的测试用例,甚至误导开发者。为了解决这个问题,作者建议引入人工补充测试,并使用“变异测试”进一步验证代码的鲁棒性。具体做法是让LLM对代码进行一些微妙但关键的修改,测试是否能够捕捉到这些改动。


优化代码结构以适配LLM

为了让LLM更好地融入实际项目,作者提出了以下几点建议:

  1. 模块化设计:将每个目录拆分为独立可测试的子模块,每个模块包含:
    • shared.go:共享定义和全局变量;
    • x.go:单一功能的实现;
    • x_test.go:对应功能的测试。
  2. 提供上下文:为模型生成的代码提供必要的背景信息,如依赖文档和示例代码。
  3. 限制模型的工作范围:一次只让模型处理一个特定子目录,减少分心。

这种结构不仅能减少问题代码进入生产环境的风险,还鼓励代码解耦和单元测试优先的开发方式。最终,代码会趋于高内聚低耦合,既功能丰富,又易于维护。


结语:谨慎拥抱新工具

最后,作者提醒读者,AI技术更新日新月异,今天的优化方案可能很快被淘汰。因此,不必着急用这种方法重构已有的大型项目,但对于新项目来说,这是一种值得尝试的开发思路。


http://www.ppmy.cn/server/159501.html

相关文章

基于 Python 的毕设选题管理系统设计与实现

标题:基于 Python 的毕设选题管理系统设计与实现 内容:1.摘要 本文介绍了一个基于 Python 的毕设选题管理系统的设计与实现。该系统旨在解决传统毕设选题管理方式中存在的效率低下、信息不透明等问题。通过使用 Python 语言和相关技术,实现了对毕设选题的信息化管理…

2019-Android-高级面试题总结-从java语言到AIDL使用与原理

4.通过线程池 线程池的工作原理:线程池可以减少创建和销毁线程的次数,从而减少系统资源的消耗,当一个任务提交到线程池时 a. 首先判断核心线程池中的线程是否已经满了,如果没满,则创建一个核心线程执行任务&#xff0…

DATACOM-华为数通解决方案SDN、iMaster

华为数通解决方案 四大引擎华为数通解决方案园区网络WLAN数据中心广域承载SD-WAN 四大引擎 引擎设备举例举例设备介绍园区网络解决方案AirEngineAirEngine 5761S-11NetEngineNetEngine40E - X16A超宽 2T 单板:业界领先的超宽 2T 单板,可向 400G 端口、4T…

【微信小程序】5|我的页面 | 我的咖啡店-综合实训

我的页面 引言 本文将详细解析如何实现一个包含登录注册、多个功能模块跳转以及特定功能展示的“我的”页面。我们将使用 Vant Weapp 组件库来简化开发过程,并确保代码的高级性和条理性。 1. 项目结构 首先,确保你的项目结构如下所示: - …

Kubernetes 部署 RabbitMQ 集群教程

本文介绍如何在 Kubernetes 中部署 RabbitMQ 集群,包含从命名空间创建到配置 NFS 存储的详细步骤。 参考文档: RabbitMQ 集群部署NFS StorageClass 创建 部署步骤 1. 创建命名空间 kubectl create ns rabbitmq2. 创建 RBAC 权限 创建文件 rabbitmq…

9分布式微服务架构

分布式微服务架构不光需要从架构上的设计优化系统,还要在编码上优化达到最好的效果 中心化的设计 中心化的设计比较简单,分布式集群中的角色分为两种,管理者和被管理者。 在一个分布式或者集群中,管理者角色管理着其他处理实际…

Spring Boot 中实现图片文件压缩

图片文件压缩是 Web 应用中常见的需求,尤其是在处理用户上传或动态生成的图片时。压缩图片不仅可以减少服务器的存储空间,还能大幅提高网页加载速度和用户体验。在本文中,我们将探讨如何在 Spring Boot 中实现图片压缩,并提供接口…

STM32 FreeRTOS 信号量

信号量的简介 reeRTOS中的信号量是一种用于任务间同步和资源管理的机制。信号量可以是二进制的(只能取0或1)也可以是计数型的(可以是任意正整数)。信号量的基本操作包括“获取”和“释放”。 比如动车上的卫生间,一个…