关于性能:单元测试执行速度(每秒多少测试?)

关于性能:单元测试执行速度(每秒多少测试?)

Unit test execution speed (how many tests per second?)

您针对单元测试(每秒#次测试)的目标执行率是什么?单个单元测试需要多长时间?

我想知道人们是否有任何特定的阈值来确定他们的测试是否太慢,或者仅仅是长时间运行的测试套件的摩擦力使您变得更好?

最后,当您确定测试需要运行得更快时,您使用什么技术来加快测试速度?

注意:集成测试显然又是另一回事了。我们严格来说是单元测试,需要尽可能频繁地运行。

响应汇总:感谢您到目前为止的出色响应。大多数建议似乎都不担心速度-专注于质量,如果速度太慢,则只选择有选择地运行它们。有具体数字的答案包括针对每次测试在10ms内达到0.5秒和1秒以内的时间,或者将整个常用测试套件的时间保持在10秒以内。

不确定它们是否都有用时,将其标记为"可接受的答案"是否正确:)


所有单元测试应在1秒内运行(也就是说,所有组合单元测试应在1秒内运行)。现在,我确定这有实际的限制,但是我有一个项目,该项目具有1000个测试,可以在笔记本电脑上快速运行。您会真正想要这样的速度,这样您的开发人员就不会担心重构模型的某些核心部分(即,在我运行这些测试的同时Lemme可以喝点咖啡... 10分钟后他回来了)。

此要求还迫使您正确设计应用程序。这意味着您的域模型是纯净的,并且包含对任何类型的持久性(文件I / O,数据库等)的零引用。单元测试都是关于测试那些业务关系的。

现在,这并不意味着您会忽略测试数据库或持久性。但是,现在这些问题被隔离在存储库之后,可以使用位于单独项目中的集成测试来单独测试这些存储库。您在编写域代码时会不断运行单元测试,然后在签入时运行一次集成测试。


目标是每秒100次测试。遵循迈克尔·费瑟(Michael Feather)的单元测试规则,可以达到目标。

在过去的CITCON讨论中提出的一个重要观点是,如果您的测试不是那么快,那么很可能就无法获得单元测试的设计优势。


如果我们严格地讲单元测试,那么我追求的是完整性而不是速度。如果运行时开始引起摩擦,请将测试分为不同的项目/类等,并仅运行与您正在从事的工作有关的测试。让Integration Server在签入上运行所有测试。


数据点-Python回归测试

这是我的笔记本电脑上用于运行Python 2.5.2的" make test"的数字:

  • 测试次数:3851(大约)
  • 执行时间:9分6秒
  • 执行速度:7次测试/秒

我们目前在大约3秒钟的时间内进行了270次测试。大约有8个测试可以执行文件IO。

在成功在每台工程师计算机上构建我们的库之后,它们会自动运行。我们拥有每晚由构建机器执行的更广泛(且耗时)的烟雾测试,或者可以在工程师机器上手动启动。

如您所见,我们尚未达到测试过于耗时的问题。对我来说10秒钟是开始变得令人厌烦的时刻,当我们开始接近它时,我们将对其进行研究。我们可能会将较低级别的库(由于它们不经常更改且几乎没有依赖关系)变得更加健壮,将其移入夜间构建或仅由构建计算机执行的配置中。

如果您发现要进行一百多个测试需要花费多于几秒钟的时间,则可能需要检查分类为单元测试的内容以及是否将其更好地视为冒烟测试。

根据您的开发领域,您的行驶里程显然会变化很大。


与速度相比,我更注重测试的可读性。但是,我仍然试图使它们变得相当快。我认为,如果它们以毫秒为单位运行,那很好。如果他们每次测试运行一秒钟或更长时间...那么您可能正在做一些应该优化的事情。

随着系统的成熟并导致构建花费数小时,缓慢的测试只会成为一个问题,在这一点上,您更有可能遇到很多类型的缓慢测试,而不是可以优化的一个或两个测试容易...因此,如果您看到大量测试每个运行数百毫秒(或更糟糕的是,每个秒),那么您可能应该立即注意,而不是等到花了这么长时间才进行数百个测试(此时)真的很难解决这个问题。)

即使如此,它也只会减少自动构建发出错误之间的时间...我认为,如果过了一个小时(甚至几个小时),就可以了。问题是在签入之前运行它们,但是可以通过选择一小部分要运行的与您正在从事的测试有关的测试来避免这种情况。如果您检入破坏未运行测试的代码,请确保修复该构建!


关于单元测试的最重要规则之一是它们应该运行得快。

How long is too long for an individual unit test?

开发人员应该能够在几秒钟内运行整个单元测试套件,而绝对不能在几分钟和几分钟内运行。无论如何,在更改代码后,开发人员应该能够快速运行它们。如果花费的时间太长,他们将不会费心运行它们,并且您会失去测试的主要好处之一。

What kind of execution rate do you aim for with your unit tests (# test per second)?

您应该使每个测试的运行时间都以毫秒为单位,任何超过1秒的时间都可能测试太多。

我们目前有大约800个测试在30秒内运行,每秒约27个测试。这包括启动运行它们所需的移动仿真器的时间。他们大多数人都花0-5毫秒(如果我没有记错的话)。

我们有一个或两个大约需要3秒钟的时间,这可能是检查的候选对象,但是重要的是整个测试套件所用的时间并不长,以至于推迟开发人员运行它,并且不会显着降低速度降低我们的持续集成能力。

我们还将可配置的超时限制设置为5秒-任何花费更长的时间都会失败。


某些框架会根据启发式方法(例如上次修改的时间)自动执行特定的单元测试。对于Ruby和Rails,AutoTest提供了更快,响应速度更快的测试执行-当我保存Rails模型app/models/foo.rb时,test/unit/foo_test.rb中的相应单元测试就会运行。

我不知道其他平台是否存在类似的东西,但这是有道理的。


How long is too long for an individual
unit test?

我会说这取决于编译速度。通常在每次编译时都要执行测试。单元测试的目的不是要放慢速度,而是要发出"什么都没有破坏,继续下去"(或"什么东西破坏了,停止")的信息。

直到这变得令人烦恼之前,我才关心测试执行速度。

危险是因为测试太慢而停止运行测试。

Finally, when you do decide the tests
need to run faster, what techniques do
you use to speed up your tests?

要做的第一件事是设法找出为什么它们太慢,并且问题出在单元测试还是被测试的代码中?

我会尝试将测试套件分为几个逻辑部分,只运行应该受到每次编译时更改的代码影响的部分。我运行其他套件的频率较低,可能每天运行一次,或者有疑问的时候我可能已经损坏了某些东西,至少在集成之前。


我以每个测试为基础来判断我的单元测试,而不是以每秒的测试数来判断。我的目标速度是500ms或更短。如果高于该值,我将调查测试以找出耗时如此之久的原因。

当我认为测试变慢时,通常表示测试做得太多。因此,仅通过将测试分解为更多测试来重构测试就可以解决问题。我还注意到测试运行缓慢的其他时间是,当测试在我的代码中显示出瓶颈时,就可以对代码进行重构了。


推荐阅读