使用 git 自动调试
想象一下,你正在开发一个复杂软件中一个更大的功能。你的实现已经完成,所有范围内的测试都通过了,你正在推送更改进行集成测试。然后,来自一个完全不同模块的一些集成测试失败了,而你完全不知道是哪个更改导致了这个问题。现在你开始分析这个问题。手动检查你的提交肯定会非常繁琐。幸运的是,git可以为你完成所有工作,而你只需要一杯咖啡就可以了。
高级命令git bisect
允许您自动运行指定的测试程序,同时它会爬过您的提交历史记录来查找错误的修订。
要求
要进行实际操作部分,需要在本地机器上进行以下设置:
- Git
- Java 8
- Maven
- Bash(Windows 上的 Cygwin)
什么是 git bisect?
git-bisect 文档的官方描述是:
使用二分查找来查找引入 bug 的提交。
假设你有很多提交,并且你知道在某个时间点,你的软件是没问题的。现在,你的软件出了问题,这意味着你在开发过程中的某个地方引入了一个 bug。gitgit bisect
会通过二分查找的方式,测试特定的提交,将修订版本图划分为好的部分和坏的部分。根据测试结果,git 会定位到有问题的提交。经过几次迭代,git 就能识别出导致问题的修订版本。
基本的 git bisect 工作流程
工作流程git bisect
包含两个主要步骤。首先,您必须指定一个修订版本范围,并限定一个好修订版本和一个坏修订版本。这些修订版本可以使用修订版本哈希、标签或任何其他 git 修订版本选择器来引用。其次,二分法 (bisect) 过程启动,git 会自动检出第一个要测试的修订版本。将测试结果返回给 git 后,git bisect good
如果成功或git bisect bad
失败,则执行该操作,并选择下一个修订版本。第二步将重复进行,直到找到第一个损坏的修订版本。
手动 git bisect
现在您已经了解了这个想法和工作流程,让我们继续动手实践。首先,从 GitHub检出包含示例项目的仓库。如您所见,该仓库包含三个文件夹:
- cake-factory:一个示例 Spring Boot Web 服务,其中包含一些需要查找的问题
- simple-bisect:关于如何手动使用 git-bisect 的参考<- 这就是我们现在要做的
- 自动二分法:如何使用自动二分法的参考,包括示例脚本
现在让我们尝试通过执行以下命令来构建蛋糕工厂
mvn -f ./cake-factory/pom.xml clean install
你会意识到,由于Citrus集成测试 失败,构建失败了。现在,让我们找出我们在哪里引入了错误。
如工作流程所示,我们必须首先设置二分场景。因此,我们必须找到一个好的版本和一个坏的版本来定义分析的边界。这两个版本都很容易找到。好的版本很可能是你分支出来的版本。坏的版本是 HEAD 版本,因为你的测试现在失败了。不过,在我们的示例中,我们将使用代码库中两个准备好的标签stable和broken 。
git bisect start # start the bisect procedure
git bisect bad broken # label the *bad* commit
git bisect good stable # label the *good* commit
或者如果您想使用较短的版本:
git bisect start broken stable # start the procedure and label the *good* and *bad* commit
现在,您的二分法已经开始,git 已经选择了一个提交来测试,并提供了提交消息以及所需迭代的估计。
到现在为止,你应该已经想出了一个测试策略来找出问题的根本原因。在我们的例子中,集成测试失败了。因此,我们将调试工作集中在集成测试上。cake-factory 的设置允许我们通过设置属性 跳过单元测试,直接开始集成测试skip.unit.test=true
。
mvn clean verify -f ./cake-factory/pom.xml -Dskip.unit.tests=true
本次修订一切正常,构建成功。现在我们需要将此结果报告给 git
git bisect good # tells git that the current revision is okay
#If the test would have been failed, you would have used 'git bisect bad'
现在你需要重复测试和报告流程。经过几次迭代后,你会发现以下提交导致了问题。 记下损坏提交的修订哈希值,并不要忘记关闭你的二分会话。
git bisect reset
如果您查看该修订版的代码,您会发现蛋糕服务提供的默认蛋糕已根据提交消息更改为vanilla,但集成测试尚未适应。
自动 git bisect
您可能已经意识到,手动执行二分法步骤会产生一些开销,而且是一项重复性任务。如果您参与的项目更复杂,涉及多个模块,这种情况会更加严重。幸运的是,它git bisect
包含一个子命令,允许我们执行特定命令或脚本测试程序,并自动报告结果。这不仅减少了所需的时间,还降低了手动重复这些步骤时出错的可能性。
git bisect run <command to execute>
要将测试结果报告给 git,你的命令或脚本必须满足以下约定:
如果测试成功,则执行的命令返回 0 码,否则返回非 0 码。
由于你只需满足此约定,你也可以使用 Python 甚至 Java 编写一些更高级的测试逻辑。不过,我建议务实一点,保持测试的简洁性。
例子
让我们回到练习。如果上一节中还没有完成,请从 GitHub 中检出包含示例项目的仓库。在“automated-bisect”文件夹中,你会找到一个findBug.sh 的bash 脚本,其中包含“手动 git bisect”部分中的测试过程代码。
#!/bin/bash
mvn clean verify -f ./cake-factory/pom.xml -Dskip.unit.tests=true
要立即执行自动化测试,只需准备一个二分法环境并将脚本传递给git bisect run
。
git bisect start broken stable
git bisect run sh automated-bisect/findBug.sh
或者,如果您有一个像findBug.sh中的一行命令,您也可以直接传递该命令,git bisect run
只要传递的命令满足合同即可。
git bisect start broken stable
git bisect run mvn clean verify -f ./cake-factory/pom.xml -Dskip.unit.tests=true
当该过程完成后,git 将显示从手册部分得知的第一个错误提交。
技巧和窍门
关于 git bisect 和 TDD
如果您遵循 TDD 生命周期来开发软件,那么使用 git-bisect 可能会遇到一些问题,因为从软件测试的角度来看,您的软件会在错误状态和功能状态之间交替变化。一旦您指定了新的测试,您的软件就会变得不稳定。如果您mvn clean install
在这种情况下执行一个简单的测试,git bisect
您将找不到包含问题根源的修订版本,因为它会与 TDD 测试导致的构建失败混淆。这也可以在我们的cake-factory示例中通过skip.unit.tests=true
从 maven 指令中删除来证明。
git bisect start broken stable
git bisect run mvn clean verify -f ./cake-factory/pom.xml
现在git bisect
会对每个失败的单元测试做出反应。这也会得出一个结果,但与我们寻找的问题的根本原因无关。
明智地设置测试场景
正如您在“关于 git bisect 和 TDD”一节中所见,如果测试场景的限制性不够,就会返回误导性的结果。因此,创建一个适合您情况的测试场景至关重要。以下几点或许能帮助您避免陷阱。
- 保持测试规模小,只测试必要且与问题直接相关的内容。这将获得正确的结果,并减少测试运行时间。
- 了解您的依赖关系如果失败的测试依赖于在开发过程中发生变化的不同模块,请记住您必须在开始测试之前在每次迭代中重建依赖关系。
- 自动化测试如果您需要多次执行某些操作,请将其自动化!不要手动执行测试。手动执行测试是一项重复性任务,会耗费大量时间。编写测试脚本,
git bisect run
剩下的交给自动化测试。 - 使用常见的“好”和“坏”候选边界。不要浪费时间思考最有效的边界。因为边界
git bisect run
本身就能帮你完成工作,所以多或少进行一次迭代并不重要。- 不合适的候选人:主要是HEAD
- 合适的候选人:
- 您从中分支的修订版本
- 您的软件的最新发布版本
- 您的分支中最后一个成功构建的修订版本。(例如,昨晚)
概括
如您所见,git bisect 是一款强大的工具,可以帮助您在 git 历史记录中查找损坏的提交。您可以定义一系列将自动检查的修订版本。如果您想了解更多关于git bisect 的信息,请访问以下链接:
本文最初于 2018 年 1 月 12 日发表于labs.consol.de
文章来源:https://dev.to/svetwer/automated-debugging-with-git-2pod