PHPUnit的数据库测试最佳实践

24
< p > < code > PHPUnit 的手册中有 一些尚未编写的章节,包括“操作”和“数据库测试最佳实践”。 < p > 使用 < code > PHPUnit 测试数据库的最佳实践是什么,特别是在 < code > MySQL 中?

Gordon,我写这个问题的原因是因为那里的答案似乎没有深入探讨,也没有参考《PHPUnit》数据库测试章节。我希望能看到更多相关内容。 - Josh Smith
1
为了让事情清晰明了:您有一个函数,基于已知的输入对数据库执行一些查询(或查询)。这将返回一个结果,现在您想检查该结果是否是您预期的吗?如果是,则从已知状态开始(您还知道实际结果应该是什么)是一个不错的开始(这就是所有重复问题中都提到的内容)。只需在每次测试运行时恢复此已知状态即可。 - wimvds
你想知道如何使用PHPUnit进行“功能测试”吗? - Andrew
@wimvds,这基本上就是我所做的,但我不知道我是否做得像应该做的那样好。我基本上在testdb上运行了mysqldump,然后手动运行mysqltestdb还原到构建服务器上的相同状态。但是,在我的测试中,是否有任何方式应该指示已知状态?是否有比每次手动运行mysqldump更自动化的方法? - Josh Smith
@Andrew,尽管应用程序的大部分是与 MySQL 的交互,但我仍然认为这些是单元测试。 - Josh Smith
2个回答

9
当我使用PHPUnit进行数据库测试时,我会在第一个包含我假定所有测试都为真的信息的测试套件开始时加载MySQL转储文件。每次测试开始时,我都会使用setupDatabase方法。该方法删除我知道已更改的表中的所有行,然后加载一个包含我需要保持为真的数据的平面XML数据集。完成后,我运行我正在测试的任何代码。最后,我使用一系列简单的方法从数据库中选择行以断言我所做的更改是否正确。
我不会说这是最佳实践,但对我而言效果还不错。我遇到的唯一问题是每次模式更改时都必须对XML数据集进行查找和替换,并且由于所有删除和插入操作,测试运行速度较慢。
Zend框架有一个有趣的PHPUnit库,允许测试将数据库表与平面XML数据集进行比较,但我还没有机会使用它。

针对数据库运行缓慢的问题:安装另一个MySQL服务器,并将其整个数据文件夹挂载到内存后端挂载点(例如,在Linux中使用tmpfs)。这将显著加快数据库的创建和操作速度。 - Mika Vatanen

3

一些无序的想法:

在每个测试的startUp()中加载fixture(带或不带db结构)到db中是很好的。它可以来自JSON或XML文件,每个表一个文件。 如果你将它与像getNthFixture($sTable, $nIndex)或countFixtures($sTable)这样的函数配对使用,你就可以轻松地测试你的查询。甚至更进一步,你可以使用[LINQ][1]从一组fixture中获取预期结果,几乎没有DB和fixture查询之间的区别。我发现在早期的原型/开发阶段很容易适应,当db结构经常变化时。添加断言以直接比较LINQ查询结果和db查询结果使创建测试成为纯粹的乐趣;)

另一个提示:db应该在每个测试方法之前重新初始化,而不是在测试用例之前。理想情况下,您应该删除基础并从完整的fixture集重新构建它。

如果可能的话,请尝试制作可与不同数据库一起使用的测试(当然,有些东西不可移植,但大多数是可移植的)。除了mysql/postgres/other_big_rdbm之外,至少要使用sqlite。

如果您正在测试框架或其他复杂系统,则可能需要模拟数据库访问单例。如果一些硬编码的东西深埋在不太灵活的orm中,它可能会让人痛苦。

好主意是记录所有未通过测试的查询,并/或在失败消息中显示它们。也适用于db错误消息。如果您正在测试大型数据库时,性能是一个问题,请尝试同时记录慢查询。

更神奇,但可能有点困难的是自动化测试,在where/having/joins中使用的所有列是否都被索引了。这可能属于Jointed Php/Database Code Sniffer (tm)而不是单元测试,并且不是很容易实现,但一旦使用,就可以极大地保证代码的质量。

另一个来自个人经验的好建议:始终为验证字符集添加测试,特别是如果您使用多种不同的语言。ISO-8859-1世界非常小;)

[1]: http://phplinq.codeplex.com/ LINQ


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接