借助大语言模型加速大规模测试迁移

2025-08-12   出处: medium  作/译者:Charles Covey-Brandt/溜的一比

借助大语言模型加速大规模测试迁移
Airbnb近期完成了首个大规模大语言模型(LLM)驱动的代码迁移项目,将近3,500个React组件测试文件从Enzyme迁移至React Testing Library(RTL)。最初我们预估手动迁移需耗费1.5年工程时间,但通过结合前沿模型与自动化方案,仅用6周便完成了全部迁移。
本文将重点解析:

  • 迁移过程中遭遇的独特挑战
  • LLM如何高效解决此类问题
  • 我们如何构建可扩展的迁移工具链

背景

2020年,Airbnb开始在新React组件测试开发中全面采用React Testing Library(RTL),标志着逐步脱离Enzyme的转型开端。尽管Enzyme自2015年以来表现优异,但其针对早期React版本设计,且深度访问组件内部状态的特性已与现代React测试实践脱节。由于框架底层差异,我们无法直接替换框架(差异详情)。同时,直接删除Enzyme文件会导致测试覆盖率显著下降。因此,我们需要一种自动化方案,在保留原始测试意图和覆盖率的前提下完成迁移。

实施方法

2023年中,Airbnb黑客马拉松团队证明:大语言模型可在数日内完成数百个Enzyme文件到RTL的转换。基于这一成果,2024年我们构建了可扩展的LLM驱动迁移流水线:

  1. 文件验证和重构步骤
    我们首先将迁移分解为一系列自动化的验证和重构步骤。可以将其想象成一个生产管道:每个文件依次经过验证阶段,当某个检查失败时,我们引入 LLM 来修复它。
    我们像状态机一样建模这个流程,只有在前一个状态的验证通过后,文件才会移动到下一个状态:

(图表显示重构步骤:Enzyme重构 → 修复Jest → 修复ESLint → 标记完成)

这种基于步骤的方法为我们的自动化管道提供了坚实的基础。它使我们能够跟踪进度,提高特定步骤的失败率,并在需要时重新运行文件或步骤。基于步骤的方法还使我们能够同时运行数百个文件的迁移,这对于快速迁移简单文件以及逐步处理迁移后期的长尾文件至关重要。 2. 重试循环与动态提示
在迁移初期,我们尝试了不同的提示词工程策略,以提高每个文件的迁移成功率。然而,在基于步骤的方法之上,我们发现提高结果的最有效途径就是简单地使用蛮力:多次重试步骤,直到它们通过或达到限制。我们更新了步骤,使用动态提示进行每次重试,将验证错误和文件的最新版本提供给 LLM,并构建了一个循环运行程序,每个步骤最多运行可配置次数。

对于给定的步骤 N,如果文件存在错误,我们会重试验证并尝试修复错误,除非达到最大重试次数或文件不再包含错误。

通过这个简单的重试循环,我们发现可以成功地迁移大量简单到中等复杂度的测试文件,有些在几次重试后成功,大多数在 10 次尝试内成功。

  1. 上下文增强

对于复杂度达到一定水平的测试文件,仅仅增加重试次数效果很好。然而,为了处理具有复杂的测试状态设置或过度间接性的文件,我们发现最佳方法是将尽可能多的相关上下文推入提示词中。

到迁移结束时,我们的提示词已扩展到 40,000 到 100,000 个标记之间,引入了多达 50 个相关文件、大量手动编写的少样本示例,以及来自同一项目的现有、编写良好且通过测试的文件示例

每个提示词包括:

  • 被测试组件的源代码
  • 我们正在迁移的测试文件
  • 步骤的验证失败
  • 来自同一目录的相关测试(保持团队特定模式)
  • 通用迁移指南和常见解决方案

以下是实际中的样子(为了可读性大幅简化):

const prompt = [
  '将此Enzyme测试转换为RTL:',
  `关联测试代码:\n${siblingTestFilesSourceCode}`,
  `RTL示例:\n${reactTestingLibraryExamples}`,
  `导入语句:\n${nearestImportSourceCode}`,
  `组件源码:\n${componentFileSourceCode}`,
  `待迁移测试:\n${testFileSourceCode}`,
].join('\n\n');

这种丰富的上下文方法被证明对这些更复杂的文件非常有效 —— LLM 能够更好地理解团队特定模式、常见的测试方法以及代码库的整体架构。
我们应注意到,尽管在此步骤中我们进行了一些提示词工程,但主要的成功驱动因素是我们选择了正确的相关文件(寻找附近文件、来自同一项目的良好示例文 件、 筛选与组件相关的文件等),而不是将提示词工程做到完美。
在构建和测试了包含重试和丰富上下文的迁移脚本后,当我们运行第一次批量运行时,我们仅用 4 个小时就成功地迁移了目标文件的 75%。

  1. 从75%到97%:系统性优化

75% 的成功率确实令人兴奋,但它仍然使我们面临近 900 个文件未能通过基于步骤的验证标准。为了处理这个长尾问题,我们需要一种系统性方法来了解剩余文件卡在何处,并改进迁移脚本以解决这些问题。我们也希望先广泛地处理,以积极地减少剩余文件数量,而不是陷入最困难的迁移案例中。

为此,我们在迁移工具中构建了两个功能。

首先,我们构建了一个简单的系统,通过在文件上添加自动生成的注释来记录每个迁移步骤的状态,以让我们了解脚本面临的常见问题。以下是代码注释的样子:

// MIGRATION STATUS: {"enzyme":"done","jest":{"passed":8,"failed":2,"total":10,"skipped":0,"successRate":80},"eslint":"pending","tsc":"pending",}

其次,我们添加了可以轻松重新运行单个文件或路径模式的功能,并根据它们卡住的具体步骤进行筛选:

$ llm-bulk-migration --step=fix-jest --match=project-abc/**

使用这两个功能,我们可以快速运行反馈循环以改进提示词和工具:

  1. 运行所有剩余失败文件,以找到 LLM 卡住的常见问题
  2. 选择 5 到 10 个体现常见问题的文件样本
  3. 更新提示词和脚本以解决该问题
  4. 重新运行失败文件样本以验证修复
  5. 通过再次运行所有剩余文件重复此过程

在运行此 “采样、调整、清扫” 循环 4 天后,我们将完成的文件从占总文件的 75% 提高到 97%,只剩下不到 100 个文件。到这一点,我们已经对许多长尾文件进行了 50 到 100 次的重新尝试,似乎我们已经达到了通过自动化可以修复的上限。而不是投入更多的调整,我们选择手动修复剩余文件,基于基线(失败)重构,以减少这些文件完成的时间。

结果和影响

借助验证和重构管道、重试循环和扩展上下文,我们能够在短短 4 小时内自动迁移了 75% 的目标文件。

使用 “采样、调整和清扫” 策略,经过 4 天的提示词和脚本改进,我们达到了 3.5K 原始 Enzyme 文件的 97%。

对于没有通过自动化完成的剩余 3% 文件,我们的脚本为手动干预提供了很好的基线,使我们能够在另一周内完成这些剩余文件的迁移。

最重要的是,我们能够在保持原始测试意图和总体代码覆盖率的同时替换 Enzyme。即使在迁移的长尾部分有高重试次数,包括 LLM API 使用和 6 周工程时间在内的总成本,也远远比我们最初估计的手动迁移效率更高。

后续计划

此次迁移凸显了 LLM 在大规模代码转换中的强大功能。我们计划扩展这种方法,开发更复杂的迁移工具,并探索 LLM 驱动自动化的新的应用场景,以提升开发人员的工作效率。


声明:本文为本站编辑转载,文章版权归原作者所有。文章内容为作者个人观点,本站只提供转载参考(依行业惯例严格标明出处和作译者),目的在于传递更多专业信息,普惠测试相关从业者,开源分享,推动行业交流和进步。 如涉及作品内容、版权和其它问题,请原作者及时与本站联系(QQ:1017718740),我们将第一时间进行处理。本站拥有对此声明的最终解释权!欢迎大家通过新浪微博(@测试窝)或微信公众号(测试窝)关注我们,与我们的编辑和其他窝友交流。
/60 人阅读/0 条评论 发表评论

登录 后发表评论
最新文章