tSQLt - 如何检查 table 值是否已按特定值更改

tSQLt - How to check if the table values have changed by certain value

在 tSQLt 中,我们可以使用 AssertEqualsTable 命令比较 2 tables。

但是,有什么方法可以断言 table 中的值是否发生了一定程度的变化?

例如:

Table答:AccID|余额

Table B:账户ID|余额

tSQLt 中是否有任何方法可以比较这两个 tables 以检查余额是否移动了一定数量(比如 100)?如果变化超过 +/-100,则失败?

解决方法是使用通常的 SQL 逻辑 - 即 - 我们可以在 AccID 上加入两个 table,然后计算余额差异并在 where 子句中强制执行标准,以便仅显示相差 +/-100 的 AccID。然后只有上面returns0条记录的输出才允许测试成功。

tSQLt 是一个单元测试框架,所以单元测试的基本结构应该是:

Assemble 其中可能包括:

  • 伪造 tables、视图或函数,监视任何程序
  • 设置测试需要预先存在的任何数据
  • 定义任何预期的结果集(例如,如果测试来自 查看)

并非所有测试都有 Assemble 步骤

行动: 通常这将是对存储过程或函数的调用或从视图调用 SELECT。 如果测试 table 约束或触发器,此步骤可能涉及将数据插入 table 大多数测试将有一个 Act 步骤,尽管这不是强制性的 - 例如 Assemble 步骤可能会伪造并填充一些 tables 驱动特定视图的内容并定义预期结果,然后 Assert 步骤可用于将视图的全部内容与预期结果集进行比较。

断言 其中可能包括:

  • 比较SELECT语句的结果,查看内容, 具有预定义结果集的函数或过程输出
  • 检查是否抛出异常
  • 正在检查是否调用了另一个存储过程(使用 tSQLt.SpyProcedure)
  • 等等

每个测试都应该(最好是完全)一个断言(尽管用于测试异常的代码行将位于行为之前)。

因此,考虑到上述情况和您的要求,数据只能因某些操作(在过程或触发器中,或通过直接 DML 语句)而更改,因此您的测试必须有一个 行动步。我看不出您将如何编写 tSQLt 测试来断言 any 数据更改在您的容忍范围内,而不管更改它的过程如何。你什么时候运行那个测试?经过哪个过程或所有过程?那不是单元测试,而是集成测试。事实上,可以说它实际上是您 application/program 逻辑的一部分。

如果您需要确保对值的更改永远不会超出数据库中的容差级别(跨两个 tables),您可以尝试这样的事情:

1) 如果插入或更新到 Table A,Table 上余额列中的值,则使用引发异常的触发器A 大于或小于 table B

中的等效值

2) 为该触发器编写第一个测试,断言如果 Table A 中的值在您的容忍度范围内更改,则不会抛出任何错误。该逻辑可能如下所示:

Assemble: 假 TableA 和 TableB (tSQLt.Faketable) 将触发器重新应用到假 TableA (tSQLt.ApplyTrigger) 在 TableA 和 tableB 中添加一行代表您的起点

断言: 调用 tSQLt.ExpectNoException

行动: 使用范围内的值更新 TableA 中的行

3) 为该触发器编写下一个测试,断言如果 Table A 中的值更改超出您的容忍级别,则会抛出错误。

Assemble: 假 TableA 和 TableB (tSQLt.Faketable) 将触发器重新应用到假 TableA (tSQLt.ApplyTrigger) 在 TableA 和 tableB 中添加一行代表您的起点

断言: 调用 tSQLt.ExpectException,可选择定义预期的错误编号 and/or 消息

行动: 使用超出容忍水平的值更新 TableA 中的行。

我强烈建议您先练习 test-first 开发,因此从编写两个测试开始,第一个应该通过,第二个将失败。然后,当您创建触发器时,两个测试都应该通过,并且您可以证明在正面和负面情况下所需的逻辑都是有效的。

最后,这种数据库驱动的逻辑方法的问题是您的应用程序将不得不处理这个错误。这种逻辑可能更适合放在应用程序中。数据库毕竟不是,python 所以在这种情况下 LBYL (Look Before You Leap) 比 EAFP (Easier to Ask Forgiveness that Permission)