Answers:
不,不是,原因有两个:
提交应该很快。例如,一次耗时500毫秒的提交太慢,将鼓励开发人员更加谨慎地提交。鉴于在任何大于Hello World的项目上,您都会进行数十或数百个测试,因此在预提交过程中运行它们将花费太多时间。
当然,对于具有数千个测试的大型项目而言,情况会变得更糟,这些测试在分布式体系结构上运行几分钟,或者在一台计算机上运行数周或数月。
最糟糕的是,您无法做得更快。具有100个单元测试的小型Python项目在普通服务器上至少需要花费一秒钟的时间才能运行,但通常需要更长的时间。对于C#应用程序,由于编译时间的原因,平均时间为4-5秒。
从那时起,您可以额外花一万美元购买一台更好的服务器,这将减少时间,但不会减少太多,或者在多台服务器上运行测试,这只会减慢速度。
当您有成千上万的测试(以及功能,系统和集成测试)时,这两种方法都可以带来很高的回报,从而使它们可以在数分钟而不是数周的时间内运行,但这对于小型项目没有帮助。
相反,您可以做的是:
鼓励开发人员在提交之前运行与他们在本地修改的代码密切相关的测试。他们可能无法运行数千个单元测试,但可以运行五分之十。
确保找到相关的测试并运行它们实际上很容易(而且很快)。例如,Visual Studio能够检测自上次运行以来所做的更改可能会影响哪些测试。其他IDE /平台/语言/框架可能具有类似的功能。
保持提交尽可能快。强制执行样式规则是可以的,因为通常它是唯一的执行位置,并且因为这样的检查通常非常快。只要保持快速,就可以进行静态分析,这种情况很少发生。运行单元测试不正确。
在Continuous Integration服务器上运行单元测试。
确保在开发人员中断构建时(或在单元测试失败时)自动通知开发人员,如果您将编译器视为检查可以引入代码的某些错误的工具,这几乎是同一回事。
例如,转到网页检查最后的构建不是解决方案。应该自动通知他们。显示弹出窗口或发送SMS是如何通知它们的两个示例。
确保开发人员了解破坏构建(或使回归测试失败)不是可以的,并且一旦发生,他们的首要任务就是修复它。老板是否要求明天交付高优先级功能并不重要:构建失败,应该对其进行修复。
托管存储库的服务器不应运行自定义代码(例如单元测试),尤其是出于安全原因。这些原因已经在GitLab的同一服务器上的CI运行器中说明了吗?
另一方面,如果您的想法是从预提交钩子在构建服务器上启动进程,那么它将减慢更多的提交速度。
让我成为不同意我的回答者的人。
这在TFS世界中被称为门控签到,我希望在其他地方也可以。当您尝试通过门控检入检入到分支时,将架子集发送到服务器,以确保您的更改得以构建并且指定的(读取:全部)单元测试通过。如果他们不这样做,它会通知您您是破坏了构建的坏猴子。如果是这样,更改将进入源代码管理(是!)。
以我的经验,门控检入是成功进行单元测试的最重要过程之一-进而扩展到软件质量。
为什么?
当然,您最初带来的好处是-当您完成检入门和一组可靠的测试时,每个变更集都是“稳定的”。您节省了“上一次构建良好时是什么时候?”的所有开销(以及潜在的错误)。-所有版本都足以对抗。
是的,构建和运行测试需要时间。以我的经验,一个大小合适的C#应用和5k单元测试需要5到10分钟。我不在乎。是的,人们应该经常入住。但是他们还应该经常更新任务,或者检查电子邮件,或者喝点咖啡或其他数十种“不使用代码”的事情,这些事情构成了软件工程师在那段时间的工作。签出错误的代码要比5到10分钟花费更多。
提交应该运行得很快。当我提交一些代码时,我希望将其推送到服务器。我不想等待几分钟来进行一系列测试。我对我推送到服务器的内容负责,不需要任何人使用提交挂钩来照顾我。
就是说,一旦到达服务器,就应该对其进行分析,单元测试并立即(或在很短的时间内)构建。这会提醒我以下事实:单元测试已损坏,或者未编译,或者使静态分析工具显示出混乱。完成的速度越快(构建和分析),我的反馈就越快,并且我能够更快地解决它(思想并没有完全从我的大脑中移出)。
所以不,不要在客户端的提交钩子中放置测试等。如果有必要,请将它们放在提交后的服务器上(因为您没有CI服务器),或者放在CI构建服务器上,并在出现问题时适当地向我发出警报。但是不要一开始就阻止提交。
我还应该指出,在对“测试驱动开发”进行一些解释之后,应该检入先中断的单元测试。这演示并记录了该错误的存在。然后,稍后的检入将是修复单元测试的代码。在单元测试通过之前阻止任何签入会降低签入未能记录问题的单元测试的有效值。
Commits should run fast.
这有什么好处?我很好奇,因为我们当前使用门控签入。通常我的签到工作是一个小时左右的时间,所以5分钟的等待并不重要。事实上,我也发现,其正常的时候,我是在赶时间的验证构建在捕获愚蠢的错误非常有用(如冲的结果)
catching silly mistakes (as a result of rushing)
完全是@Justin 。总的来说,匆匆忙忙是软件工程中的不良做法。罗伯特·C·马丁(Robert C. Martin)建议编写类似手术的代码youtube.com/watch?v=p0O1VVqRSK0
原则上,我认为防止人们对主线进行更改以破坏构建是有意义的。也就是说,对存储库的主分支进行更改的过程应要求确保所有测试仍然通过。就浪费时间而言,中断构建成本太高,以至于项目上的所有工程师都无法做其他事情。
但是,提交挂钩的特定解决方案不是一个好的计划。
Breaking the build is simply too costly in terms of lost time for all engineers on the project
我建议使用某种构建通知工具来避免所有工程师最终在每次损坏的构建中浪费时间
我必须等待成功的构建和对主分支的每次提交进行测试,这确实很糟糕,我认为每个人都对此表示同意。
但是还有其他方法可以实现一致的主分支。这是一个建议,在TFS中的门控签入方面有点类似,但是可以推广到具有分支的任何版本控制系统,尽管我将主要使用git术语:
有一个暂存分支,您只能将其在开发分支和主分支之间提交合并
设置一个挂钩,该挂钩可启动构建或将其排队并在暂存分支上对提交进行测试,但这不会使提交者等待
在成功的构建和测试中,如果最新,则自动使主分支前进
注意:不要自动合并到主分支中,因为经过测试的合并(如果不是从主分支的角度来看是向前合并),当合并到主分支中且提交之间存在提交时,可能会失败
作为结果:
禁止人员在可能的情况下自动提交到主分支,如果存在漏洞或强制执行此操作在技术上不可行,也将作为正式流程的一部分
至少,一旦这是基本原则,您就可以确保没有人会无意间或没有恶意。永远不要尝试这样做。
您必须在以下两者之间进行选择:
如果先前的尚未构建且未经测试的合并失败,则单个分段分支将使否则成功的合并实际上失败
至少,您会知道哪个合并失败并需要有人纠正,但是对于进一步的构建和测试的结果,两者之间的合并是不容易被跟踪的(通过版本控制系统)。
您可以查看文件注释(或责备),但是有时文件的更改(例如,配置)会在意外的地方生成错误。但是,这是相当罕见的事件。
多个分段分支,这将允许无冲突的成功合并到达主分支
即使在某些其他登台分支具有不冲突的合并失败的情况下。可追溯性要好一些,至少在一个合并没有预期到另一个合并带来影响的情况下。再次重申,这种情况很少见,不必每天或每周担心。
要在大多数情况下进行无冲突的合并,重要的是明智地拆分分段分支,例如按团队,按层或按组件/项目/系统/解决方案(即使您命名)。
如果同时将主分支转发到另一个合并,则必须再次合并。希望这不是非冲突合并或很少冲突的问题。
与封闭式签入相比,这样做的好处是您可以保证主分支正常工作,因为主分支只允许前进,而不会自动将更改与它们之间提交的内容合并。因此,第三点是本质区别。
我要说的是,这取决于项目和在“提交”上运行的自动化测试的范围。
如果您希望在签入触发器中运行的测试确实非常快,或者如果开发人员工作流程无论如何都要在签入后强制执行某些管理工作,那么我认为这没什么大不了,而是迫使开发人员仅检查绝对可以运行最基本的测试的东西。(我假设您只会在这样的触发器上运行最基本的测试。)
而且我认为,在速度/工作流程允许的情况下,不要将更改推送给未通过测试的其他开发人员是一件好事-并且您仅知道运行它们是否失败。
您在问题中写出“ commit ... to remote branch”,这对我意味着这(a)开发人员每隔几分钟就不会做一次,因此稍作等待是可以接受的,并且(b)之后这样的提交,代码更改可能会影响其他开发人员,因此可能需要进行其他检查。
对于这样的操作,我可以同意“不要在等待时让您的开发人员打起大拇指”的其他答案。