人们如何单元测试他们的业务应用程序?我已经看到很多单元测试的例子都是"简单测试"的例子.防爆.一个计算器.人们如何对数据量大的应用进行单元测试?你是如何整理样本数据的?在许多情况下,一个测试的数据可能根本不适用于另一个测试,这使得很难只拥有一个测试数据库?
测试代码的数据访问部分非常简单.它正在测试所有针对似乎难以测试的数据的方法.例如,想象一个发布过程,其中存在大量数据访问以确定发布的内容,数字被调整等.发生了许多临时步骤(并且需要进行测试)以及之后的测试以确保发布是成功的.其中一些步骤实际上可能是存储过程.
在过去,我尝试将测试数据插入测试数据库,然后运行测试,但老实说,编写这种代码非常痛苦(并且容易出错).我还尝试过预先构建测试数据库并回滚更改.这工作正常,但在许多地方你也不能轻易做到这一点(许多人会说这是集成测试;所以,我仍然需要能够以某种方式测试它).
如果答案是没有一种很好的方法来处理这个问题,而且目前只是很糟糕,那么知道也是有用的.
任何想法,想法,建议或提示都表示赞赏.
我的自动功能测试通常遵循以下两种模式中的一种:
数据库连接测试
当我有连接到数据库的自动化测试时,我通常会创建一个测试数据库模板,该模板具有足够的数据用于所有测试.运行自动化测试时,将为每个测试从模板生成一个新的测试数据库.必须不断重新生成测试数据库,因为测试通常会更改数据.随着测试的增加,我通常会将更多数据附加到测试数据库模板中.
这种测试方法有一些很好的优点.显而易见的优点是测试还可以运用您的架构.另一个优点是,在设置初始测试后,大多数新测试将能够重用现有的测试数据.这样可以轻松添加更多测试.
缺点是测试数据库将变得难以处理.因为数据通常会在一次添加一个测试,所以它会不一致,甚至可能不切实际.当存在重大的数据库模式更改时,您最终会诅咒设置测试数据库的人(对我来说这通常意味着我最终诅咒自己).
如果您无法随意生成新的测试数据库,这种测试方式显然不起作用.
模拟持久层测试
对于此模式,您可以创建与测试用例一起使用的模拟对象.这些模拟对象拦截对数据库的调用,以便您可以以编程方式提供适当的结果.基本上,当您测试的代码调用该findCustomerByName()方法时,将调用您的模拟对象而不是持久层.
使用模拟对象测试的好处是你可以非常具体.通常,有些执行路径在无模拟对象的自动化测试中无法实现.它们还使您无法维护大量的单片测试数据.
另一个好处是缺乏外部依赖性.因为模拟对象模拟持久层,所以测试不再依赖于数据库.在选择要选择的模式时,这通常是决定性因素.在处理具有严格许可条款的旧数据库系统或数据库时,模拟对象似乎更具吸引力.
模拟对象的缺点是它们经常导致大量额外的测试代码.这并不可怕,因为几乎任何数量的测试代码在运行测试的次数分摊时都很便宜,但是获得更多的测试代码然后生成代码会很烦人.
当我尝试使用回滚解决方案来处理这些集成测试时,我必须赞同 @Phil Bennett 的评论。
我在这里有一篇关于集成测试数据访问层的非常详细的文章
我不仅展示了示例数据访问类、基类和示例数据库事务固定装置类,还展示了带有示例数据的完整 CRUD 集成测试。使用这种方法,您不需要多个测试数据库,因为您可以控制每个测试进入的数据,并且在测试完成后,事务全部回滚,因此您的数据库是干净的。
关于应用程序内部的单元测试业务逻辑,我还会支持 @Phil 和 @Mark 的评论,因为如果您模拟出业务对象具有的所有依赖项,那么一次测试一个实体的应用程序逻辑就会变得非常简单;)
编辑:那么您是否正在寻找一个巨大的集成测试来验证从逻辑预数据库/存储过程运行到逻辑的所有内容,最后在返回时进行验证?如果是这样,您可以将其分为两个步骤:
1 - 对数据推送到数据访问代码之前发生的逻辑进行单元测试。例如,如果您有一些代码根据某些属性计算一些数字 - 编写一个测试,仅检查此 1 函数的逻辑是否按照您的要求执行。模拟对数据访问类的任何依赖,这样您就可以在单独的应用程序逻辑测试中忽略它。
2 - 集成测试在获取操作数据(来自我们单元测试的先前方法)并调用适当的存储过程后发生的逻辑。在数据特定的测试类中执行此操作,以便您可以在完成后回滚。存储过程运行后,对数据库进行查询以获取您的对象,因为我们已经对数据执行了一些逻辑并验证它具有您期望的值(存储过程后逻辑 /etc )
如果您需要数据库中的一个条目来运行存储过程,只需在运行其中包含您的逻辑的存储过程之前插入该数据即可。例如,如果您有需要测试的产品,则可能需要插入供应商和类别条目,因此在插入产品之前,请对供应商和类别进行快速而粗略的插入,以便您的产品插入按计划进行。
| 归档时间: |
|
| 查看次数: |
2004 次 |
| 最近记录: |