如何使用git对分:使用单元测试确定错误提交?

如何使用git对分:使用单元测试确定错误提交?,git,unit-testing,git-bisect,Git,Unit Testing,Git Bisect,我是git新手,刚刚发现了“git对分”。当您可以使用一个新编写的单元测试(之前没有)检查错误时,它通常是如何使用的 假设我们有一个包含单元测试的存储库,但是——通常情况下——它们并不完整。在某些版本中,我们发现某个功能不起作用,但我们知道它以前在某些版本中存在。不幸的是,该特性没有通过单元测试进行检查。我现在想做的是: 编写测试用例(当然首先失败) 使用此测试用例,使用git bisect查找引入错误的提交 更正错误并提交修复(以及测试用例) 这个用例有一个问题。当git bisect检查旧版

我是git新手,刚刚发现了“git对分”。当您可以使用一个新编写的单元测试(之前没有)检查错误时,它通常是如何使用的

假设我们有一个包含单元测试的存储库,但是——通常情况下——它们并不完整。在某些版本中,我们发现某个功能不起作用,但我们知道它以前在某些版本中存在。不幸的是,该特性没有通过单元测试进行检查。我现在想做的是:

  • 编写测试用例(当然首先失败)
  • 使用此测试用例,使用git bisect查找引入错误的提交
  • 更正错误并提交修复(以及测试用例)
  • 这个用例有一个问题。当git bisect检查旧版本时,刚刚插入的测试用例将不存在,因此我不能使用它来检查错误。我可以尝试不提交测试,而是将其作为本地更改保存。但是想象一下测试文件在两者之间的某个版本中发生了更改,我很可能会遇到合并冲突


    那怎么办呢?git bisect通常是如何使用的?

    我通常使用bisect来识别何时引入了错误,这样我就可以查看单个提交以找出错误的原因。当我知道有些东西过去有用,但现在不行时,这很有用。我首先选择或找到一个有效的旧提交,用“
    git bisect good”
    标记它,用“
    git bisect bad”
    标记头部,然后通过bisect工作,直到git告诉我导致问题的提交。有时我可以在开始这个过程之前编写单元测试,有时我在看到引入错误的代码之前无法编写

    所以,假设我有单元测试,或者其他一些代码或脚本,在经历git对分过程时,我需要在每个点使用它们。我走的时候把它藏起来很有用。所以

    git stash save blah
    git bisect bad (and now I'm on a new commit)
    git stash pop
    mvn clean test
    
    git stash save blah
    git bisect good
    git stash pop
    mvn clean test
    
    等等。

    首先,在尝试此操作之前,确保您的
    git状态
    是干净的-我建议使用一个脚本调用
    git reset--hard
    ,这样任何未提交的更改都将丢失

    一种方法是首先将最近测试的源代码复制到存储库历史记录中(或存储库外部)从未跟踪过的某个位置。然后编写一个脚本:

  • 将最近的测试复制到源代码树中的适当位置
  • 运行测试,保存返回代码
  • 是否执行
    git重置--hard
    以清除步骤1中的更改
  • 退出,返回代码从2保存
  • 然后,在将两个提交标记为good和bad以给出
    git-bisect
    开始的地方之后,您可以使用
    git-bisect运行您的-SCRIPT
    来查找最近的单元测试可能失败的第一个提交

    这种方法本质上就是建议的,它说:

    您可能经常会发现,在对分会话期间,您希望在头文件中进行临时修改(例如s/#define DEBUG 0/#define DEBUG 1/),或者“没有此提交的修订版需要应用此修补程序来解决此对分没有解决的另一个问题” 对应用于正在测试的修订版感兴趣

    为了应对这种情况,在内部git对分找到下一个要测试的修订版后,脚本可以在编译之前应用补丁,运行真正的测试,然后确定修订版(可能带有所需的补丁)是否通过测试,然后将树倒回原始状态。最后,脚本应该以实际测试的状态退出,以让“git bisect run”命令循环确定bisect会话的最终结果


    您没有提到您使用的是哪种技术,所以我将以Ruby为例,这是我最熟悉的。不过,同样的原则也应该适用于其他技术

  • 将最新的测试文件放在项目目录之外。这里我假设它在
    /tmp/my_test.rb

  • 在存储库中,创建一个小型shell脚本,例如,
    test\u runner.sh

    #/副秘书长/垃圾箱/环境卫生
    cp-f/tmp/my_test.rb test/my_test.rb#这可能会覆盖一些旧的测试文件
    ruby test/my_test.rb#针对您使用的任何测试运行程序进行更改
    测试结果=$?
    git checkout test/my_test.rb#撤消可能已进行的任何更改
    退出$test\u结果
    
  • 将提交标记为好/坏,通常使用
    bisect

  • 使用
    git bisect run test\u runner.sh
    去喝杯咖啡,让git帮你找到bug