我使用的很多web应用程序都是由后端复杂程度不同的数据库驱动的.通常,有一个ORM层与业务和表示逻辑分开.这使得业务逻辑的单元测试相当简单;事情可以在离散的模块中实现,测试所需的任何数据都可以通过对象模拟来伪造.

但是测试ORM和数据库本身总是充满问题和妥协.

这些年来,我try 了一些策略,但没有一个能让我完全满意.

  • 使用已知数据加载测试数据库.针对ORM运行测试,并确认返回的数据正确.这里的缺点是您的测试数据库必须跟上应用程序数据库中的任何模式更改,并且可能不同步.它还依赖于人工数据,并且可能不会expose 由于愚蠢的用户输入而发生的错误.最后,如果测试数据库很小,它不会揭示诸如缺少索引之类的低效问题.(好的,最后一个并不是单元测试应该用来做的,但也没什么坏处.)

  • 加载生产数据库的副本并对其进行测试.这里的问题是,您可能在任何给定时间都不知道生产数据库中有什么;如果数据随着时间的推移发生变化,您的测试可能需要重写.

有人指出,这两种策略都依赖于特定的数据,单元测试应该只测试功能.为此,我看到了一些建议:

  • 使用模拟数据库服务器,并且只判断ORM是否发送了正确的查询来响应给定的方法调用.

您使用了什么策略来测试数据库驱动的应用程序(如果有的话)?什么对你来说效果最好?

推荐答案

实际上,我已经使用了您的第一种方法,取得了相当大的成功,但使用的方式略有不同,我认为它可以解决您的一些问题:

  1. 将整个架构和用于创建它的脚本保留在源代码管理中,以便任何人都可以在签出后创建当前数据库架构.此外,将示例数据保存在由构建过程的一部分加载的数据文件中.当您发现导致错误的数据时,请将其添加到示例数据中,以判断错误不会再次出现.

  2. 使用持续集成服务器构建数据库架构、加载示例数据并运行测试.这就是我们保持测试数据库同步的方式(在每次测试运行时重建它).虽然这需要CI服务器访问和拥有其自己的专用数据库实例,但我要说的是,让我们的数据库架构每天构建3次可以极大地帮助发现错误,而这些错误可能要到交付之前(如果不是更晚的话)才会被发现.我不能说我在每次提交之前重新构建了模式.有人知道吗?有了这种方法,您就不必这样做了(也许我们应该这样做,但如果有人忘记了,那也没什么大不了的).

  3. 对于我的团队来说,用户输入是在应用程序级别(而不是db)完成的,因此这是通过标准单元测试进行测试的.

正在加载生产数据库副本:
这是我在上一份工作中使用的方法.这是几个问题造成的巨大痛苦:

  1. 从生产版本来看,副本会过时
  2. 将对副本的架构进行更改,并且不会传播到生产系统.在这一点上,我们会有不同的模式.一点也不好玩.

模拟数据库服务器:
在我目前的工作中,我们也是这样做的.在每次提交之后,我们对注入了模拟数据库访问器的应用程序代码执行单元测试.然后,我们每天执行上述的完整数据库构建三次.我绝对推荐这两种方法.

Database相关问答推荐

如果我想支持我的工作负载,我需要多少个 node ?

文件存储的推荐位置 - 在数据库或其他什么地方?

如何识别 DB2 端口号

跨不同数据库创建视图

Postgres - 如何返回缺失数据计数为 0 的行?

如何在 Oracle 中找到指向一条记录的外键依赖项?

用于 sql server 的免费国家、城市数据库

db:schema:load vs db:migrate with capistrano

是否可以在ORDER BY子句之后放置任何可能造成安全风险的内容?

Tornado 的非阻塞 ORM?

Redis: Get key and value on expiration

获取错误函数 to_date(timestamp without time zone, unknown) 不存在

如何在远程服务器上备份 MySQL 数据库?

从原始物理文件中恢复 postgreSQL 数据库

如何在 Google AppEngine 上实现自动增量

如何在每个 SQLite 行中插入唯一 ID?

标准化人类皮肤 colored颜色 以进行用户交互

如何以 SYS 身份在 Java 中连接到 Oracle?

为什么 DBMS 不支持 ASSERTION

NoSQL 数据库是否使用或需要索引?