从手动到自动:用GitHub Copilot实现TDD的最佳实践

从手动到自动:用GitHub Copilot实现TDD的最佳实践

sjmyuan 7 2025-05-01

引言

最近,我们团队用上了GitHub Copilot,大家迫不及待的在各种场景下进行尝试,看看它究竟能节省我们多少工作量。然而,在尝试的过程中有人提出了一个问题:在使用GitHub Copilot的情况下,我们该如何进行测试驱动开发(TDD)?甚至,我们是否还需要TDD?

为了回答这个问题,我们探索了几种不同的方案,并从以下三个维度对每种方案进行了评价:

  • 开发体验:开发人员在开发过程中的流畅程度以及认知负荷。
  • 任务粒度:开发人员需要将任务分解到何种粒度才能适配GitHub Copilot的执行能力。
  • 任务完成度:GitHub Copilot生成代码的质量,以及人工修改的频率。

本文将详细介绍这些尝试及其评估结果,并探讨在AI编程助手的支持下,TDD的角色和未来。

尝试过的方案

在探索如何结合GitHub Copilot与TDD的过程中,我们统一使用了以下需求场景作为测试基础:

需求描述

**用户故事:**  
“作为用户,我想将包存入储物柜并收到一张票据,以便安全存放我的物品,并在之后使用票据取回。”

**验收标准:**  
1. 假设用户已将包放入储物柜,  
   当他们关闭柜门时,  
   系统应提供一张带有唯一标识的票据。

2. 假设用户持有有效票据,  
   当他们在储物柜站点扫描或输入票据时,  
   对应的储物柜应解锁,允许他们取回包。

3. 假设用户尝试在没有有效票据的情况下取包,  
   当他们试图解锁储物柜时,  
   应显示一条错误消息,提示访问被拒绝。

4. 假设所有储物柜已被占用,  
   当用户试图存储包时,  
   应显示通知告知储物柜不可用,并建议稍后再试。

5. 假设储物柜系统跟踪容量,  
   当某个储物柜在取包后变得可用时,  
   系统应更新其状态以允许存储新的包。

基于上述需求,我们尝试了以下几种主要方案,并对其效果进行了评估。

1. 传统的TDD开发方式 + 代码补全

在此方案中,我们依然遵循传统的TDD开发流程,但在编写代码时利用GitHub Copilot的代码补全功能自动生成部分内容。

点击观看完整视频

评价

  • 开发体验:流畅度较低。开发人员的思维模式需要在手动编写代码和等待代码生成之间频繁切换,容易分散注意力。当生成的代码质量不高时,会感到挫败感并浪费时间。
  • 任务粒度:任务分解粒度较细,属于行级粒度。开发人员需要随时准备调整代码,缺乏明确的任务界限和节奏。
  • 任务完成度:最低。人工修改生成代码的频率最高,效率较低。

2. 传统的TDD开发方式 + 注释 + 代码补全

在此方案中,我们在使用代码补全功能的基础上,增加了注释来引导GitHub Copilot生成更大粒度、更准确的代码。

点击观看完整视频

评价:

  • 开发体验:流畅度一般。由于注释比代码更具灵活性,开发人员可以将注意力集中在任务描述上,减少了对语法或格式的关注,从而降低了认知负荷。
  • 任务粒度:任务分解粒度适中,属于函数级别。对于跨函数任务,有时仍需人工调整代码。
  • 任务完成度:一般。通过调整注释重新生成代码,人工修改的频率有所降低,但仍需一定干预。

3. 传统的TDD开发方式 + Edit + 提示词

此方案基于GitHub Copilot的Edit功能,我们将TDD的每个步骤写成提示词,以生成符合要求的代码。

点击观看完整视频

评价:

  • 开发体验:流畅度较高。开发人员的思维模式专注于编写提示词和审查代码,进一步减少了认知负荷。不过,测试和重构仍需单独编写提示词。
  • 任务粒度:任务分解粒度较大,属于开发流程级别,生成的测试不再局限于单个测试用例,而是覆盖多个场景。
  • 任务完成度:较高。通过提示词修改或重新生成代码,人工修改代码的频率较低。

4. Agent + TDD提示词

最后,我们尝试了GitHub Copilot的Agent模式,并结合TDD提示词进行开发。提示词的内容如下:

# User Task Breakdown  

Decompose high-level software requirements into discrete, testable functionalities and implement them using the Test-Driven Development (TDD) methodology. For each functionality, follow these steps:  

   1. **Write Focused Tests**: Create precise unit tests for a single functionality or requirement, ensuring coverage of all possible scenarios, edge cases, and invalid inputs.  
   2. **Confirm Test Failure**: Execute the tests to verify they fail initially, confirming their validity before implementation begins.  
   3. **Implement Minimal Code**: Write the simplest code required to pass the tests, avoiding over-engineering or adding features not directly related to the current test cases.  
   4. **Verify Implementation**: Re-run the tests to confirm that the implemented code passes all test cases successfully. Debug and refine as necessary.  
   5. **Refactor**: Improve the code’s structure, readability, and performance while maintaining functionality, ensuring no tests break during the process.  
   6. **Validate Refactoring**: Run the tests again after refactoring to ensure the updated code still passes all test cases without introducing regressions.

提示词的大体意思是,当GitHub Copilot拿到用户任务后,需要先将其拆分成具体的、可测试的功能,然后用TDD的方式实现每个功能,具体实现步骤需要包含写测试、运行测试确保测试失败、写实现、运行测试验证实现、重构和运行测试验证重构。

我们将上述提示词放到文件.github/copilot-instructions.md中,使用Agent模式进行开发。

点击观看完整视频

评价:

  • 开发体验:流畅度高。开发人员的思维模式专注于提示词编写和代码审查,无需单独为测试和重构编写提示词,大幅减少了认知负荷。
  • 任务粒度:任务分解粒度最大,属于功能级别。开发人员无需关心开发流程细节,只需专注于任务分解和代码审查。
  • 任务完成度:最高。可在运行测试之前通过GitHub Copilot Chat或手动调整代码,人工修改代码的频率最低。但需要注意的是,Agent模式偶尔可能偏离TDD开发模式,这可能与提示词的设计有关。

还需要TDD么?

传统的TDD是一种需要人为维护的实践方式,容易因各种原因被忽视或遗弃。然而,从上述尝试中可以看出,我们完全可以将TDD的实践流程以提示词的形式嵌入GitHub Copilot,并通过代码库进行统一管理。这样一来,所有团队成员都可以采用一致的开发流程。

从这个角度来看,TDD本身似乎不再需要被单独强调。这并不意味着TDD的重要性降低了,而是说AI编程助手赋予了我们将TDD自动化的可能性。TDD不再是一项需要投入大量时间和精力去培训才能掌握的技能,也不再是开发中的可选项,而是一种被脚本化、自动化到日常工作中的标准流程。开发人员可以将更多的精力投入到需求澄清、任务划分和代码审查上。

这种转变类似于持续集成(CI)的发展历程。在没有CI之前,开发人员需要手动在本地完成编译和测试,并牢记最佳实践流程。然而,这种流程无法强制执行。随着CI工具的普及,这些实践被固化到脚本中,开发人员无需再花费额外精力去关注它们,从而可以专注于其他更重要的工作。同时,遗漏或出错的概率也大幅降低。

因此,TDD的角色正在从一项需要人为驱动的实践转变为一种由AI编程助手自动化的流程。这不仅提升了开发效率,还确保了更高的代码质量。

总结

TDD只是众多传统开发实践中可以被自动化的例子之一。通过将团队的最佳实践以提示词的形式嵌入AI编程助手,我们可以实现更高程度的标准化和一致性。AI编程助手就像一位知识丰富但经验不足的初级开发人员,我们可以通过精心设计的提示词规范其行为,为团队成员提供一致的使用体验。

这种方式不仅有助于提升团队成员的能力,还能优化开发流程。未来,随着AI工具的进一步发展,我们或许能够将更多复杂的开发实践自动化,从而释放开发人员的创造力,让他们能够专注于解决更具挑战性的问题。

让我们拥抱AI的力量,在自动化的基础上重新定义软件开发的最佳实践。这不仅是技术的进步,更是开发方式的一次深刻变革。