TDD的良好git工作流是什么?

23
我很喜欢Gitflow分支模型,但我不确定在哪里放置TDD周期 - 我应该只是使用一个功能分支,并在每次编写或通过测试(以及重构后)时提交吗?创建子分支并将“完成”的单元合并到功能分支中?我应该在每次失败的测试后提交还是只有在它通过后再提交?
这是我目前在一个功能分支上做的事情:
1.编写测试,提交 2.由于不存在接口,测试可能会产生错误,请修复此错误,修改提交 3.使(现在只有失败的)测试通过,修改提交 4.重构,新提交 5.回到1

@shioyama,你是把新的但失败的测试提交还是只在它们通过后提交?如果你确认我的假设已经是一个答案,欢迎将其发布为答案。 - Tobias Kienzler
1
回答你的问题:我尽量不提交任何破坏测试套件的内容,但我的功能分支并未包含在我的travis-ci文件中,因此如果它们失败了,我就不会收到电子邮件或其他通知。只有当我将它们(未修复)合并到develop或master分支时才会发生这种情况。 - Chris Salzberg
5个回答

9
我不确定这是否具有代表性,但作为一名开发人员,我使用git-flow,并且以下是(大致)我的新功能工作流程:
  • 创建一个功能分支
  • 编写一个高级别的验收测试(cucumber),它带有@wip(正在进行中)标签,因此现在不包括在测试套件中,并将其提交到新分支
  • (有时候)编写用于集成测试边缘情况的rspec请求测试,并将其提交到功能分支中
  • 为功能的各个组件和每个大致定义的“单元”编写低级别的测试(rspec / jasmine),并将其提交到功能分支中
  • 当功能完成足够,可以通过验收测试时,将@wip标记去掉,确保它通过,并提交到功能分支
  • 使用git merge(而不是git flow finish)将功能分支合并到develop分支中。这样留下了功能分支,因此如果需要更新功能,则可以稍后更新。
  • 一旦将分支合并到develop中,travis-ci会对其运行完整的测试套件,如果出现任何问题,我就会收到电子邮件。(我只在我的.travis.yml文件中包含develop和master分支)
我应该说,这是我的“理想”工作流程 - 实际上我经常违反这些规则:在编写测试之前提交未经测试的更改,在实际构思高级验收测试之前开始处理功能的某些部分等。因为基本上只有我提交项目,所以我有自由去那样做;如果您在较大的团队中工作,则必须严格遵守任何工作流程。
无论如何,这就是我做的方式。我很乐意听取其他人的意见,因此我已经赞同了这个问题。
更新:
撰写此文后,我意识到有一种情况我与上述流程不同,即当我添加“功能”时,这些功能并非严格属于正常面向用户的类型(即用户不会注意到的内容)。例如,在开发应用程序的早期阶段,我们决定使用backbone.js来构建我们的js代码-因此,我为其创建了一个功能分支,并向各种现有的黄瓜功能添加了@javascript标签。一旦分支粗略地能够使用backbone.js完成与HTML视图相同的操作,则将其合并回来。
我还计划切换到使用require.js,在这种情况下,我也将为执行此操作创建一个功能分支,并在完成后将其合并回来。不会有高级别的集成测试-只要现有的测试通过,就一切正常。

+1,我也是一个人组成的团队 :-7 还要感谢提到黄瓜,我会去看看它(或者寻找 Python 的替代品)。 - Tobias Kienzler
1
Cucumber在某些方面很有用,但最近我开始认为在rspec中完成所有事情可能会更好。请看这篇文章:http://jimmycuadra.com/posts/please-don-t-use-cucumber - Chris Salzberg

6

我认为一个好的简单指南是在每次你处于 "绿色 " 状态时提交代码,或者至少在每个 测试周期 之后:

  • 要么是 Red -> Green -> Refactor -> 提交
  • 要么是 Red -> Green -> 提交 -> Refactor -> 提交

2
我认为在重构之前进行提交(第二个选项)会更好一些,否则有风险破坏功能代码。如果后来发现错误,历史记录中会有两个实现版本可供检查。:-7 - Tobias Kienzler
我同意第二个选项更安全(每次绿灯时都提交),但有些人可能认为这太麻烦了。如果您在短周期内工作,您实际上没有太多机会在RGR迭代之间破坏功能代码。在大多数情况下,您总是可以撤消更改。 - Assaf Stone
嗯,也许我们甚至可以让单元测试自动创建一个名称为“green”或“red”的提交,或者修改最后一次提交的名称。然后稍后仍然可以进行变基... - Tobias Kienzler

5

我的工作流程非常相似,但要考虑更好地利用暂存区。

  1. 编写测试,git add。
  2. 由于不存在的接口可能会导致测试失败,因此需要修复,git add。
  3. 使(现在只有失败的)测试通过,git commit。
  4. 重构,git commit --amend。
  5. 返回1。

这强制执行纪录每个提交时所有测试都通过的纪律。在1-3阶段中,我可以随时使用git checkout回滚到上一个git add。


2

什么时候应该提交?简单来说就是:

  1. 我能描述我正在提交的内容,并且用一条有意义的提交信息吗?
  2. 是否有任何原因让我想要回到这个点或从这个点开始进行比较?

这意味着真正取决于个人。如果你从未发现自己在某个阶段进行过 diff,可能是因为你修复得足够快,以至于你仍然记得你改变了什么,那么你就不需要提交。但是,这也没有什么坏处,除了输入命令所需的时间。

如果你觉得一个步骤不值得长期提交,另一个选择是只做 git add。这样,git diff 将向你展示自添加以来的变化,而 git diff --cached 将向你展示之前的变化。这就是我做的,因为我希望我的提交可以编译并通过单元测试。这样,回到一个已知的良好状态就很容易。


1
我不认为有一种特定于TDD的提交工作流程,我尽量遵守的唯一规则是尽量不将带有失败测试的提交推送到主分支(除非它已经失败了)。在我的功能分支上,通常只测试与功能相关的测试,但在执行合并回主分支时,所有测试都将得到验证。如果我知道提交确实会导致某些功能测试失败或其他原因使其如此,那么只有在这种情况下我才会将其标记为wip。在更实际的方面,我认为更好的做法是多加小心,避免将提交推送到错误的分支。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接