我正在尝试设置 SpecFlow 进行集成/验收测试。我们的产品在 Sqlite 中有一个支持数据库(虽然不是很大)。
但这实际上被证明是一个有点棘手的问题;如何为测试建立数据库模型?
我想知道其他人使用什么模式来对支持数据库进行集成/验收测试。
我可以想到以下方法:
- 将数据库编译到包含测试的程序集中,然后为每个测试对其进行卷影复制。虽然看起来很慢。
- 我可以在内存中创建数据库并用预先确定的数据填充它。
- 我可以在内存中创建数据库,并以某种方式让吉文斯填充数据库。这看起来会让测试变得非常膨胀,但可能会给他们更多的控制权并使测试不那么脆弱。
- 我可以抽象每个数据库交互并使用模拟。不喜欢这个想法,因为我也想用它来测试数据库交互。
- 将数据库编译到测试中,并依靠清理代码将其返回到基本状态(这对我来说似乎很狡猾)。不想用事务来执行此操作,因为某些测试会进行多次交互(因此写入一个项目,然后尝试使用不同的权限读回它)。
在考虑之前How进行测试,我想您可能会发现它值得一看What你想测试。
从...开始什么数据,我发现采用单个元素或少量元素并想象围绕它们的一组事件确实很有帮助,以便为您提供正确的测试数据来运行测试。例如;
- 如果您在医疗保健系统上工作,您可能会定义一个人“Bob”,然后生成他的生活事件。鲍勃出生于 37 年前的今天,小时候从自行车上摔下来,摔断了手臂,后来结了婚,并育有两个孩子。
- 如果您正在开发金融交易系统,您可能会查看几支股票的开盘价和收盘价之间的一天,例如“MSFT”和“APPL”。在这一天,您可能会看到一个从低处开始攀登,另一个从高处开始下降。一个消息的传出,扭转了他们的命运。
现在您已经有了可以实际评估哪些场景真正适合您的数据的信息,例如“MSFT”和“APPL”全天可能会有数千次价格变化,因此生成 Givens 和 Mocks 将非常耗时。这些数据适合预先捕获。另一方面,“Bob”数据在使用生成的数据时效果特别好,因为数据总是可以更改,因此今天是他的生日。
您的问题似乎不需要考虑的一件事是更新您的数据。例如,您可能希望有一组在实体生命周期的各个阶段工作的测试,例如一些测试涉及“Baby Bob”,其他测试涉及“10yr old Bob”或“Married Bob”等。如果您的数据库是只读的,那么如果您可以编写测试以使它们不这样做,那么这不是问题see其他数据,但有时您想通过测试构建一个故事。如果您的测试确实更改了数据,那么您将无法确保测试按顺序运行(请参阅MSTest 有序测试或 mbUnit DependsOn),或者您可以分离您的测试,以便它们各自处理一个独立的数据实体(如果您的实体可以在单行中描述,这很好,但当您必须读取许多表才能获取它时,这会变得更困难) 。
您可能还想考虑什么代码当您正在测试时,您可以在不同的测试集中改变方法。我目前正在开发一个多层应用程序,该应用程序具有 UI 视图、视图模型、客户端模型、多个通信系统和服务器模型。我也对这些进行了不同的测试。我有一些在单层中工作的测试,模拟其他层以保持我的测试较小。其他测试启动本地服务器和本地客户端,并将两者直接连接起来。最后,我进行了一些测试,启动完整的服务器进程,通过 EMS 进行通信,并使用除 UI 视图之外的所有内容运行一些简单的客户端操作。
现在要真正回答你的问题,
-
卷影复制您的数据库- 是的,我已经使用 SQLServer Developer 完成了一次此操作,并且在运行测试之前复制了一个 xxx.mdb。然而,一些现代测试框架将并行运行测试,例如NCrunch,所以这就打破了。
-
创建数据库并预填充- 没有完成这个,但我担心的是当测试将数据库更改为意外状态时会发生什么。当其他测试没有做错任何事情时,它们就会失败。
-
创建数据库并使用Givens- 我已经通过 NUnit 完成了这个
[SetupFixture]
在 Linq-to-sql DB 之上。您仍然担心并行测试运行,并且必须平衡给定的粒度(请参阅StackOverflow-BDD 场景何时变得过于具体),并且您遇到了数据更新顺序/数据隔离问题,但这可以很好地帮助您处理数据故事并在整个测试过程中增长数据。另一方面,如果一个测试失败并使数据处于不良状态,您可能会遇到很多失败,但至少您只需要查看第一个失败的测试。对于在工作站上的开发人员来说,这种测试也不会很好地发挥作用,因为他们不能只运行单个测试,特别是使用 NCrunch 等工具,它只能运行代码已更改的测试。
-
模拟数据库这就是我现在选择做事的方式。诀窍在于,如果您个人遵循相当严格的 TDD 流程,仅测试您正在使用的方法,那么您实际上最终会得到一些测试数据库交互的层,例如
[Test]DALLayerTests.ShouldReadARowAndCreatePOCO()
,但大多数其他人使用模拟数据来测试实际发生的情况,例如[Test]BusinessObjectPersonTests.ShouldGetBirthdayCongratulations()
.
-
使用清理代码- 从未尝试过,听起来很危险:-)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)