在工作中,我们发现我们的测试套件已经到了重复运行的速度太慢,我真的不喜欢.整个套件至少需要5分钟,后端数据对象测试需要3分钟以上.所以,我很想知道人们如何进行测试.
目前,我们有一个具有实时架构和_test架构的数据库服务器.当测试运行时,它首先运行一个SQL脚本,该脚本说明如何填充测试数据库(并清除可能妨碍的任何旧数据).几乎所有测试都会发生这种情况 从我所看到的,这是我们测试中最大的瓶颈 - 我刚刚介绍了一个测试,设置数据库需要大约800ms,然后每个后续测试运行大约10ms.
我一直试图找出一些解决方案,这是我到目前为止所发现的:
将测试模式填充一次,并在每次测试结束时回滚更改.
这似乎是最简单的解决方案,但它确实意味着我们将不得不添加一些特殊情况来测试依赖于回滚的事情(即错误处理测试).
尽可能模拟数据库
我们将为正在测试的数据对象设置数据库,但是模拟它依赖的任何东西.对我而言,由于两个原因,这似乎并不出色.首先,当我们设置数据库时,由于外键依赖性,我们仍然(通常)会得到更多的行.其次,大多数数据对象模型并不真正与其他模型交互,它们只是做JOIN.
运行相同的系统,但使用转储和RAMFS
我们不是运行大型SQL查询,而是加载数据库转储.测试服务器将在RAMFS分区上运行,并希望带来一些速度优势.
我无法测试这个,因为我在OSX上,从我所看到的,没有ramfs支持.
还有其他一些选择,比如使用SQLite,但这不是我们的选择,因为我们依赖于一些PostgreSQL特定的扩展.
HALP!:)
一个有趣的问题.通过你试图对数据库进行单元测试的事情的声音,这是一个坏主意.您希望这些测试尽可能快.如果您正在使用数据层,那么您可能会考虑将其模拟出来以使其在内存中运行.针对模拟数据层进行测试.
不要放弃你当前的测试,它们肯定是有价值的,应该作为每晚的一部分运行,或者在不减速的开发盒中构建.
编辑
在回答你的评论时,确实没有一种加速测试的好方法.将测试分成两组,一组对于开发人员来说很快,另一组对于连续构建来说更合适也许是最好的选择.你可以扔更快的硬件,SSD或RAM磁盘将是一个很好的起点.
在亚音速项目(.net的ORM)中,我们遇到了同样的问题,我们的测试需要花费一分钟,因为他们不仅要打一个数据库,还要打我们目前支持的每个数据库的实例.我们采取了这些测试,而不是针对数据库运行它们,看看它们是否返回了我们预期的数据,我们假设数据库将返回正确的结果,并且只是对生成的SQL进行了字符串比较.当我们进行红绿色开发时,我们只运行字符串比较单元测试.在提交之前和构建服务器上,我们运行完整的套件.
编辑第二个
我发现自己需要针对数据库运行测试以确认我的查询是正确的.我所做的是在内存中建立SQLite数据库并对其运行查询.性能非常好,它确实可以很好地模拟真实数据库,因为它是一个.
在有效地使用遗留代码时,Michael Feathers写道(第10页)
单元测试运行得很快.如果它们没有快速运行,它们就不是单元测试.
其他类型的测试通常伪装成单元测试.在以下情况下,测试不是单元测试:
- 它与数据库进行对话.
- 它通过网络进行通信.
- 它触及文件系统.
- 您必须对您的环境执行特殊操作(例如编辑配置文件)才能运行它.
做这些事情的测试也不错.通常他们值得写作,你通常会将它们写在单元测试中.但是,能够将它们与真正的单元测试分开是很重要的,这样您可以保留一组测试,以便在进行更改时可以快速运行.
如果你不能快速保持你的单元测试,它们会失去价值,因为开发人员不会一直运行它们.具体而言,Feathers将慢速单元测试定义为需要十分之一秒或更长时间才能执行的测试.
保持您的集成测试实际与数据库通信,触摸文件系统等,在他们自己的测试套件中与您的单元测试分开.这些仍然需要尽可能频繁地运行以保持反馈回路短路,但是你可以逃避运行它们,比如说,每天只运行几次.
不要搁置您的集成测试而忘记它们!自动执行和报告结果.如果您正在使用持续集成服务器,请添加另一个除了定期运行测试之外什么都不做的项目.
在单元测试中,对数据库层使用模拟或伪造.必须重复相同的工作将变得乏味,并且避免它的愿望将倾向于通过将数据库访问集中在几个类中并将您的逻辑推入域模型来改进您的设计,这是您想要测试的内容的地方是.
| 归档时间: |
|
| 查看次数: |
336 次 |
| 最近记录: |