如何使用PHP SimpleTest框架设置数据库测试

时间:2008-10-06 16:52:44

标签: php database unit-testing tdd simpletest

我正在使用SimpleTest,这是一个基于PHP的单元测试框架。我正在测试新代码,它将处理从数据库中存储和检索网站注释。我对如何构建项目以测试数据库访问代码感到茫然。

我正在寻找有关在PHP应用程序中测试db代码的最佳实践的任何建议。例子真的很棒。进一步阅读的网站很棒。

谢天谢地。 :)

8 个答案:

答案 0 :(得分:3)

这是一个老问题,但我想我会添加一些我们对此有的具体经验。

其他海报在技术上是正确的,这是一种集成测试的形式,但是从我坐在那里的MySQL经常有太多逻辑在单元测试中被删除。如果您像我们一样拥有大量复杂的服务,这些服务严重依赖于MySQL(通常每个服务有几个表),那么拥有一个包含测试查询逻辑的强大测试框架非常方便。我们在单元测试中模拟了大量的依赖项,但不是MySQL。

我们有一组包装simpletest的类来提供这个功能。它的工作原理如下:

  • 创建每个数据库表的说明存储在tests/etc/schemas/table.sql的文件中。它包含架构数据以及测试期望找到的所有固定数据的插入。
  • 每个需要数据库的测试都扩展了一个Test_DbCase类,它提供了构建表的功能。
  • 引导类负责在构造和销毁时创建和删除数据库。
  • 在运行时,测试调用setUp方法中的loadTables('foo', 'bar')以执行foo.sqlbar.sql中的sql命令。
  • 对罐装数据进行测试......其余的显而易见。

我们拥有的另一个工具是bash脚本,可以更轻松地创建table.sql文件。这非常方便,因为否则我们会手工编写SQL - 您可以使用现有的一组表,在MySQL中设置所有数据,然后将其导出以基本创建测试文件。

这对我们来说非常有效,尽管我们最终不得不自己滚动很多。

答案 1 :(得分:1)

我有一个本地数据库,专门用于使用已知名称和数据库用户名/密码进行单元测试。单元测试被硬编码到该位置,但不同的开发人员可以根据需要覆盖这些变量。

然后在每次测试之前,每个表TRUNCATE。这比删除/创建表或数据库本身更快

注意:测试后截断!这样,如果测试失败,您将拥有数据库的当前状态,这通常有助于诊断问题。

答案 2 :(得分:1)

您可能希望允许PHP创建数据并将数据提供给临时表/数据库并在该表/数据库上进行测试。然后,您不必手动重置数据库。大多数框架都有数据库操作库,以使其更容易。在前端可能需要一些时间,但是稍后当您进行更改时,可以让您更快地进行测试。

答案 3 :(得分:0)

对数据库的测试通常表明测试结果不好,可能是由于测试代码中缺少封装。您应该尝试尽可能地将与数据库交互的代码与其余代码隔离开来,使这个交互层保持如此简单,以至于您可以通过一些非常基本的测试来完成。

换句话说;处理注释的代码不应与处理数据库交互的代码相同。例如,您可以编写一个通用表模块,您的注释模型将使用该模块来访问数据库。您仍然需要测试表模块,但这应该与注释代码隔离。

答案 4 :(得分:0)

在测试数据库代码时,总是拥有与起点相同的数据库是件好事。特别是如果你进行单元测试(我假设这是这里的情况)。其中一种方法是按照Jason的建议截断所有表格,但我更喜欢在其中包含一些起始数据。您知道,您始终需要在每个数据库中都有一些“默认”数据。

此外,某些测试仅对完整数据库有意义。因此,为这些测试创建一个特殊的数据库实例。在运行某些测试之前,我有大约3或4个不同的数据库,我插件(只是复制文件)。每次都有相同的起点确保可重复性。

因此,只需准备一些好的“起点”并备份它们的数据库状态。在运行每组测试之前,请还原相应的数据库,然后运行它。

答案 5 :(得分:0)

我建议您尝试使用SimpleTest测试数据库访问代码。

相反,使用例如Selenium为您的应用程序创建功能测试:从数据库的已知状态开始时记录测试用例;然后添加注释并检查(使用Selenium的断言)内容确实存在。

这样: - 更容易设置和维护 - 您不仅验证数据库图层,还验证表示层

也就是说,如果你的数据库中有存储过程,那么使用SimpleTest - 我已经成功完成了它。基本上,创建从已知数据库状态开始的SimpleTests,然后执行一些INSERTS / UPDATES,然后运行存储过程并确保数据库的状态是您所期望的。

答案 6 :(得分:0)

如果你真的想对数据库进行测试,我建议在每次测试之前导入数据/创建表。这样,您的数据库就会在每次测试时从已知状态开始。由于性能相当昂贵,您可以在setUp中启动事务(前提是您的rdms支持它)并在tearDown中回滚。 MySql(可能是您正在使用的RDBMS)不支持嵌套事务,因此如果测试中的代码使用事务,则可能会遇到麻烦。你可以使用savepoints解决这个问题。在测试之前设置保存点,并在测试后回滚到保存点。

我仍然会坚持认为,如果你需要这么多,你应该考虑你的测试试图告诉你什么的可能性。

答案 7 :(得分:0)

我认为你应该使用ORM,并为此编写一些集成测试。如果集成测试显示它在实际环境下运行良好,那么只有在更改环境(数据库,php版本,平台等等)时才需要再次测试它。之后,您可以模拟ORM对象,而不需要连接到数据库。

所以我认为这是最好的方法,但是如果你不想使用ORM,那么你可以创建一个测试数据库并模拟数据库连接(PDO)对象。在这种情况下,您可以在testCases的setUp和tearDown部分中创建和删除测试表。重要的是这些是集成测试,而不是单元测试,所以你不需要总是运行它们,只有当PHP和SQL服务器之间发生了某些变化时。在使用集成测试测试数据访问对象后,必须在单元测试中对其进行模拟。