为什么我应该避免使用DbUnit来测试MySQL?

时间:2012-07-16 18:58:39

标签: unit-testing tdd phpunit dbunit

我最近使用PHPUnit参与了一些TDD。 我必须测试一个数据库驱动的应用程序,并阅读DbUnit扩展,我计划在未来几周内研究和实施。

然而,我自己遇到过presentation这个人本人 - 塞巴斯蒂安·贝格曼 - 他有一张标题为“如果可以的话,避免对MySQL进行测试”的幻灯片,这对我的逃避产生了一些疑问。

有人可以解释我不应该针对MySQL进行测试的原因吗?

由于

3 个答案:

答案 0 :(得分:6)

有两个原因:

  • 它很慢(单元测试需要很快)
  • 它增加了超出您控制范围的额外故障点(当数据库连接失败时,测试真的失败吗?)

相反,作者建议你应该在内存数据库中测试你的DAL,比如SQLite。这消除了上述问题。

但是,这种方法也有其缺点 - 您可能无法将SQL从一个数据库方言移植到SQLite。这自然意味着您将无法测试DAL的MySQL特定部分。一如既往,它是双刃剑 - 你获得单元测试速度和隔离,但你失去了可信度(如果我们可以这样称呼它) - 如果它传递给SQLite,你能100%确定它适用于MySQL?

将DAL / DAO测试的核心留在集成测试阶段可能并不是一个坏主意,在这个阶段,您将再次测试它们使用的真实数据库引擎,并为单元测试留下小东西;例如映射(如果你使用ORM)。

编辑快速绝不是严格的要求 - 这只是一个很好的一般建议。在进行TDD时,您的开发人员将运行单元测试很多(以这种方式思考;每次提交本地repo /每次重要代码更改都需要通过运行单元测试来检查代码库完整性) - 也许不是全部,但肯定是一些。您希望此过程快速。

现在,慢速测试通常会这样结束:

  • “伙计,这件事情很慢......”
  • “也许我只能运行其中几个...我会稍后休息”
  • 此时我们知道以后永远不会来
  • “嘿,我的最后一次提交没有破坏任何东西,我根本没有进行任何测试!”
  • “为什么我会运行它们?”

编写未运行的测试,几乎杀死了编写它们的目的。

  

这件事发生在和我一起工作的朋友身上;他的团队运行测试套件+/- 20分钟(DAL测试做得不好,IoC容器参与测试),开发人员开始运行一些测试,很快就会出现“当前建立破坏者“电子邮件成为日常事物。他们有相当大的套件,但破坏测试并不那么糟糕

总的来说,您的方法似乎是正确的 - 我不会将测试移到SQLite。像我建议的那样,使用集成测试套件测试数据库层(这样它可以单独运行,而不是常规的单元测试套件)。

答案 1 :(得分:3)

我完全不同意塞巴斯蒂安·贝格曼写的第33张幻灯片的标题。

  

(因为来自幻灯片的消息很容易被误解,我是   确保在他的演讲中他解释了真正的意义)

如他的介绍调试糟透了,但测试岩石

如果真实环境使用mySQL,你必须对mySQL进行测试。否则你会发现自己正在调试SQLite和mySQL之间的区别。

我相信他的方向是针对开发人员而不是单元测试人员,从这个意义上说,我还建议开发人员尽一切努力使他们的代码数据库保持中立。它将提高项目整体生命周期的质量,而不仅仅是单位测试人员。它甚至可以保护mySQL本身的功能改进。 (过去有很多问题)。

但是在测试使用SQL的单个代码时,无论您已经进行了哪些其他测试,必须对照真实内容进行测试。

我的做法是创建一个数据库连接的抽象层,并让测试与该层做出反应。随后,我为每个要测试的数据库服务器创建不同的具体类。

根据该环境,我们可以测试针对SQLite的频率,但真正的测试每天至少运行一次。

答案 2 :(得分:2)

我使用DbUnit来测试我的模型(谈到MVC,包括ORM模型),因为它们与数据库密切相关。对于其他一切(主要是控制器),我使用模拟对象。

单元测试的基本思想是一次只测试一个应用程序代码单元(这是一个类),因此最好避免使用DB,除非代码直接使用它。

当然,性能至关重要。例如,我有~500个模型测试,几乎所有模型都使用数据库和固定装置。在相当快的计算机上执行所有这些测试大约需要30-40秒。代码覆盖率报告生成大约需要一分钟。