@sql 单元测试

In this article on SQL unit testing, we will talk about how to isolate SQL unit tests from dependencies and how to use fake tables in SQL unit tests, so that we will able to develop more robust and less fragile SQL unit tests.

在有关SQL单元测试的本文中,我们将讨论如何将SQL单元测试与依赖项隔离开来,以及如何在SQL单元测试中使用伪造表,以便我们能够开发更健壮和更不易损坏SQL单元测试。

At first, let’s make a basic definition of the SQL unit testing approach. The main purpose of the SQL unit test is to test each programmable and atomic part of the database objects (stored procedure, function and etc.) to ensure that these programmable parts work correctly. According to this definition, SQL unit testing focuses on programmable and atomic parts, for this reason, we should prevent external factors and other influences which affects the SQL unit tests behaves because dependencies may cause the SQL unit tests fails to fail. At this point, let’s try to find out the answer of “Why we struggle to isolate SQL unit test from dependencies” over a scenario.

首先,让我们对SQL单元测试方法进行基本定义。 SQL单元测试的主要目的是测试数据库对象的每个可编程部分和原子部分(存储过程,函数等),以确保这些可编程部分正常工作。 根据此定义,SQL单元测试集中在可编程部分和原子部分上,因此,我们应该防止由于依赖关系可能导致SQL单元测试失败而导致影响SQL单元测试行为的外部因素和其他影响。 在这一点上,让我们尝试找出方案中“为什么我们为什么难以将SQL单元测试与依赖项隔离”的答案。

Imagine that, we want to test a stored procedure and this stored procedure involves a table and this table data directly affects the stored procedure result set. Under these circumstances, we need to avoid a dependency of this table in the stored procedure just because our aim is to test the behavior of the stored procedure. That’s why we must create fake table and use these fake table in the SQL unit test. In this way, SQL unit test merely focuses on the programmable part and more accurate test result occurs.

想象一下,我们要测试一个存储过程,并且该存储过程涉及一个表,并且该表数据直接影响该存储过程的结果集。 在这种情况下,仅由于我们的目的是测试存储过程的行为,我们就需要避免该表在存储过程中的依赖性。 这就是为什么我们必须创建伪表并在SQL单元测试中使用这些伪表的原因。 这样,SQL单元测试仅专注于可编程部分,并且会出现更准确的测试结果。

Note: Before going through the details of SQL unit test faking, I want to notice that if you don’t have much experience or knowledge about SQL unit testing and tSQLt framework, I would like to suggest to take a glance on the previous articles (see the TOC at bottom) which are related to SQL unit testing.

注意: 在详细介绍SQL单元测试伪造之前,我想注意到,如果您对SQL单元测试和 tSQLt框架 没有太多的经验或知识 ,我建议您浏览一下以前的文章(请参阅底部的TOC ),这些内容与SQL单元测试有关。

FakeTable简介和语法 (FakeTable introduction and syntax)

As we mentioned in the entrance part of the article, we must isolate unit tests from dependencies, particularly SQL unit test results might be directly affected by data which is stored in the tables. That’s why, we should isolate the SQL unit tests from external and uncontrolled table data because that might be influence the result of the SQL unit test.

正如我们在文章的开头部分所提到的,我们必须将单元测试与依赖项隔离开,特别是SQL单元测试结果可能会直接受表中存储数据的影响。 因此,我们应该将SQL单元测试与外部和不受控制的表数据隔离开,因为这可能会影响SQL单元测试的结果。

The tSQLt framework includes a FakeTable stored procedure and it is the good and appropriate solution for these circumstances. FakeTable creates empty copy of the original table during the test period so that we can take control of the table during the SQL unit test. Another benefit of using FakeTable is that DML (Data Manipulation Language) operations do not affect the original table because all operation is running in a transaction block.

tSQLt框架包括一个FakeTable存储过程,它是针对这些情况的良好且合适的解决方案。 FakeTable在测试期间创建原始表的空副本,以便我们可以在SQL单元测试期间控制该表。 使用FakeTable的另一个好处是DML(数据操作语言)操作不会影响原始表,因为所有操作都在事务块中运行。

Faketable takes various parameters as shown in the below;

Faketable接受各种参数,如下所示;

tSQLt.FakeTable [@TableName = ] 'table name', [[@SchemaName = ] 'schema name'] --Deprecated: do not use, will be removed in future version, [[@Identity = ] 'preserve identity'], [[@ComputedColumns = ] 'preserve computed columns'], [[@Defaults = ] 'preserve default constraints']

FakeTable用法示例 (FakeTable usage example)

Let’s make a simple demonstration to reinforce all this theoretical information. At first, we will create our sample tables which we will use in the following SQL unit test example.

让我们做一个简单的演示来增强所有这些理论信息。 首先,我们将创建示例表,将在以下SQL单元测试示例中使用该表。

DROP TABLE IF EXISTS OrderLine
DROP TABLE IF EXISTS OrderHeader
CREATE TABLE OrderHeader (OrderId INT PRIMARY KEY , OrderName VARCHAR(50))
CREATE TABLE OrderLine (OrderLineId INT PRIMARY KEY ,
OrderId INT FOREIGN  KEY REFERENCES  OrderHeader(OrderId)
,OrderAmnt INT,OrderNet AS (OrderAmnt*2) PERSISTED,OrderDate DATE DEFAULT GETDATE())
GO
CREATE OR ALTER PROC GetOrderAmntYear AS
select YEAR(OrderDate) As OrderYear,SUM(OrderAmnt) As Amnt
from OrderLine GROUP BY
YEAR(OrderDate)

As you can see in the below illustration, OrderLine table has a foreign key constraint, so we cannot insert any induvial row to OrderLine table, unless to insert a related row to OrderHeader table.

正如你可以在见下图,OrderLine的有一个外键约束,所以我们不能将任何induvial行OrderLine的 ,除非插入相关行OrderHeader表。

Now we will prove this issue through the following query.

现在,我们将通过以下查询证明此问题。

INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(20,'20190101')

As you can see in the above image, if we want to insert some test rows to OrderLine table, at first we have to insert referential rows to OrderHeader table otherwise we experienced a foreign key violation error message is returned.

如上图所示,如果我们想向OrderLine表中插入一些测试行,首先必须将引用行插入到OrderHeader表中,否则会返回外键违反错误消息。

On the other hand, GetOrderAmntYear returns a total of the OrderAmnt columns per year and we want to test this stored procedure. This stored procedure only use OrderLine table so we must break this foreign key dependency. At this point, we have to notice another important thing, in the database development environments we can’t take control under these tables’ data, because some developers or dbas data can be added or deleted data from these tables. For this reason, we cannot be sure result set of the stored procedure. This situation influences the behavior of the SQL unit test. Let’s ask the notable question, “How can we overcome this issue in the tSQLt framework?”

在另一方面,GetOrderAmntYear返回总共每年OrderAmnt列,我们要测试的这款存储过程。 此存储过程仅使用OrderLine表,因此我们必须打破此外键依赖关系。 在这一点上,我们必须注意另一个重要的事情,在数据库开发环境中,我们无法控制这些表的数据,因为可以在这些表中添加或删除某些开发人员数据或dbas数据。 因此,我们不能确定存储过程的结果集。 这种情况会影响SQL单元测试的行为。 让我们问一个值得注意的问题:“我们如何在tSQLt框架中克服这个问题?”

The tSQLt framework involves a stored procedure which name is FakeTable. Now let’s learn FakeTable usage through the following example. At first, we will create a test class and then write SQL unit test.

tSQLt框架涉及一个名为FakeTable的存储过程。 现在,通过以下示例学习FakeTable的用法。 首先,我们将创建一个测试类,然后编写SQL单元测试。

EXEC tSQLt.NewTestClass 'MockTableTest'
GO
CREATE OR ALTER PROCEDURE MockTableTest.[Test_GetOrderAmntYearStoredProcedure_PerYears]
AS
DROP TABLE IF EXISTS actual
DROP TABLE IF EXISTS expected
CREATE TABLE actual (OrderYear INT,Amnt INT)
CREATE TABLE expected (OrderYear INT,Amnt INT)EXEC tSQLt.FakeTable 'OrderLine'
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(20,'20190101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(8,'20190101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(12,'20170101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(3,'20160101')INSERT INTO actual
EXEC GetOrderAmntYearINSERT INTO expected (OrderYear,Amnt)
VALUES(2019,28),(2017,12),(2016,3)EXEC tSQLt.AssertEqualsTable  'expected', 'actual';GOEXEC tSQLt.Run 'MockTableTest.[Test_GetOrderAmntYearStoredProcedure_PerYears]'

Now, we will tackle this SQL unit test code row by row. In the below part of the SQL unit test we create a fake copy of the OrderLine table and then we insert random test values. The crucial point is that; during the SQL unit test OrderLine table contains solely the test rows so that we can exactly know the returning result set of the GetOrderAmntYear stored procedure. This exactness allows us to make a proper comparison between actual and expected tables. On the other hand, FakeTable allows us to create a plain table so that we can deactivate the constraints in the fake table. Constraints sometime might be trouble-maker for us during the test period however we can determine and deactivate constraints with help of the FakeTable parameter.

现在,我们将逐行处理此SQL单元测试代码。 在SQL单元测试的下面部分中,我们创建OrderLine表的伪副本,然后插入随机测试值。 关键是: 在SQL单元测试期间, OrderLine表仅包含测试行,因此我们可以确切地知道GetOrderAmntYear存储过程的返回结果集。 这种准确性使我们能够在实际表和预期表之间进行适当的比较。 另一方面, FakeTable允许我们创建一个普通表,以便我们可以停用伪表中的约束。 在测试期间,有时约束可能会给我们造成麻烦,但是我们可以借助FakeTable参数确定并取消约束。

EXEC tSQLt.FakeTable 'OrderLine'
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(20,'20190101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(8,'20190101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(12,'20170101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(3,'20160101')In the following part; we insert the tested stored procedure result set to the actual table.
INSERT INTO actual
EXEC GetOrderAmntYearIn the following part; we create the expected table with values.INSERT INTO expected (OrderYear,Amnt)
VALUES(2019,28),(2017,12),(2016,3)

This is the last and most important part of the SQL unit test because we compare expected and actual tables row by row through the AssertEqualsTable. AssertEqualsTable compares the actual and expected table’s data and then return the result of this matching.

这是SQL单元测试的最后也是最重要的部分,因为我们通过AssertEqualsTable逐行比较预期表和实际表。 AssertEqualsTable比较实际表和预期表的数据,然后返回此匹配的结果。

EXEC tSQLt.AssertEqualsTable  'expected', 'actual';

Faketable will be a good choice for us so that SQL unit test will be more robust and less brittle. Now, we will delete an inserted row from the actual table and then investigate the result of the unit test. In short, we will knowingly change the SQL unit test to return incorrect result. 那么Faketable将是我们的理想选择,这样SQL单元测试将更加健壮且不那么脆弱。 现在,我们将从实际表中删除插入的行,然后研究单元测试的结果。 简而言之,我们将有意更改SQL单元测试以返回错误的结果。

CREATE OR ALTER PROCEDURE MockTableTest.[Test_GetOrderAmntYearStoredProcedure_PerYears]
AS
DROP TABLE IF EXISTS actual
DROP TABLE IF EXISTS expected
CREATE TABLE actual (OrderYear INT,Amnt INT)
CREATE TABLE expected (OrderYear INT,Amnt INT)EXEC tSQLt.FakeTable 'OrderLine'
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(20,'20190101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(8,'20190101')
INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(12,'20170101')
--INSERT INTO OrderLine (OrderAmnt ,OrderDate) VALUES(4545,'20160101')INSERT INTO actual
EXEC GetOrderAmntYearINSERT INTO expected (OrderYear,Amnt)
VALUES(2019,28),(2017,12),(2016,3)EXEC tSQLt.AssertEqualsTable  'expected', 'actual';GOEXEC tSQLt.Run 'MockTableTest.[Test_GetOrderAmntYearStoredProcedure_PerYears]'

As you can see in the above illustration, the result of the unit test returns an error and it offers comprehensive information about non-matching rows. At first, we will learn the definition of the signs;

如上图所示,单元测试的结果返回一个错误,并且提供了有关不匹配行的全面信息。 首先,我们将学习标志的定义;

  • “<” specifies that the row exists in the expected table, but it does not exist in the actual table“ <”指定该行在预期表中存在,但在实际表中不存在
  • “>” specifies that the row exists in the actual table, but it does not exist in the expected table“>”指定该行在实际表中存在,但在预期表中不存在
  • “=” specifies that the row already exists in the actual and expected tables“ =”指定该行已存在于实际表和预期表中

As a result, we developed a SQL unit test with the help of the tSQLt framework. In this example, we created a SQL unit test in order to check result of the GetOrderAmntYear stored procedure. So that if somebody will make any structural changing in this stored procedure the SQL unit test will return an error so that we can recognize the issue about it. Sometimes this issue indicates a flaw or a bug. On the other hand, this change may be related to the product and may be made in the development process routine. In that case, we have to change old SQL unit test because it is not valid to test behavior of the stored procedure or we can write a new SQL unit test.

结果,我们在tSQLt框架的帮助下开发了一个SQL单元测试。 在此示例中,我们创建了一个SQL单元测试以检查GetOrderAmntYear存储过程的结果。 因此,如果有人在此存储过程中进行任何结构更改,则SQL单元测试将返回错误,以便我们可以识别有关此问题的信息。 有时,此问题表明存在缺陷或错误。 另一方面,此更改可能与产品有关,并且可能在开发过程例程中进行。 在这种情况下,我们必须更改旧SQL单元测试,因为它对测试存储过程的行为无效,或者我们可以编写新SQL单元测试。

FakeTable和计算列 (FakeTable and computed columns )

Faketable can take various parameters so that we can use it for different cases in the SQL unit test cases. Such as, if you want to preserve the computed columns in the fake table, we can set the ComputedColumns parameters as 1. Let’s make an example of it. In the following example, we will check the calculated column so that we can be sure about computed column calculation works proper.

Faketable可以采用各种参数,因此我们可以将其用于SQL单元测试用例中的不同用例。 例如,如果要保留伪表中的计算列,我们可以将ComputedColumns参数设置为1。让我们举一个例子。 在下面的示例中,我们将检查计算列,以便可以确保计算列计算工作正常。

CREATE OR ALTER PROCEDURE MockTableTest.[test_OrderLineTable_CalculatedOrderNetColumn]
AS
DROP TABLE IF EXISTS actual
DROP TABLE IF EXISTS expected
CREATE TABLE actual (OrderNet INT)
CREATE TABLE expected (OrderNet INT)EXEC tSQLt.FakeTable @TableName='OrderLine',@ComputedColumns=1
INSERT INTO OrderLine (OrderAmnt ) VALUES(20)
INSERT INTO OrderLine (OrderAmnt ) VALUES(8)
INSERT INTO OrderLine (OrderAmnt ) VALUES(12)INSERT INTO actual
SELECT OrderNet  FROM OrderLine INSERT INTO expected (OrderNet)
VALUES(40) , (16) ,(24)
EXEC tSQLt.AssertEqualsTable  'expected', 'actual';
GOEXEC tSQLt.Run 'MockTableTest.[test_OrderLineTable_CalculatedOrderNetColumn]'

As you can see in the above image; the test completed with success.

如上图所示; 测试成功完成。

结论 (Conclusion)

In this article, we discussed the SQL unit test dependency isolation approach. Dependency isolation is very significant for the SQL unit testing because it enables to develop more effective SQL unit tests so that it increases the code quality. In this article, we specifically mentioned how to use FakeTable stored procedure in the tSQLt framework and explain it with some examples.

在本文中,我们讨论了SQL单元测试依赖项隔离方法。 依赖隔离对于SQL单元测试非常重要,因为它可以开发更有效SQL单元测试,从而提高代码质量。 在本文中,我们特别提到了如何在tSQLt框架中使用FakeTable存储过程,并通过一些示例对其进行了说明。

目录 (Table of contents)

SQL Unit Testing with SSDT (SQL Server Data Tools)
SQL unit testing with the tSQLt framework for beginners
SQL Unit testing with the tSQLt framework and SQL Server Database Project integration
SQL unit testing best practices
How to use fake tables in SQL unit testing?
How to use fake functions with SQL unit testing?
SQL Unit Testing Mocking Stored Procedures
SQL Unit Testing: Working with exceptions
使用SSDT进行SQL单元测试(SQL Server数据工具)
使用tSQLt框架SQL单元测试面向初学者
使用tSQLt框架和SQL Server Database Project集成进行SQL单元测试
SQL单元测试最佳实践
如何在SQL单元测试中使用假表?
如何在SQL单元测试中使用伪函数?
SQL单元测试模拟存储过程
SQL单元测试:使用异常

翻译自: https://www.sqlshack.com/how-to-use-fake-tables-in-sql-unit-testing/

@sql 单元测试

@sql 单元测试_如何在SQL单元测试中使用假表?相关推荐

  1. pl/sql 测试函数_如何在SQL单元测试中使用伪函数?

    pl/sql 测试函数 In this article series, we are exploring SQL unit testing, in general, and also we are r ...

  2. sql小册子_如何在Microsoft Word中创建小册子

    sql小册子 Brochures are a handy marketing tool used by nearly every company in existence. Creating them ...

  3. 如果不使用 SQL Mail,如何在 SQL Server 中发送电子邮件

    如果不使用 SQL Mail,如何在 SQL Server 中发送电子邮件 察看本文应用于的产品 文章编号 : 312839 最后修改 : 2006年12月21日 修订 : 10.1 本页 概要 SQ ...

  4. sql server 数组_如何在SQL Server中实现类似数组的功能

    sql server 数组 介绍 (Introduction) I was training some Oracle DBAs in T-SQL and they asked me how to cr ...

  5. sql中日期的比较_如何在SQL中比较日期?

    sql中日期的比较 How to compare date in SQL? For example, the 'users' table has a column 'loggin' which is ...

  6. sql azure 语法_如何在SQL 2016中使用Azure Key Vault使用AlwaysOn配置TDE数据库

    sql azure 语法 One of the recent tasks I undertook on configuring Transparent Data encryption (TDE) us ...

  7. sql server只读_如何在SQL Server 2016中为可用性组配置只读路由

    sql server只读 The SQL Server Always On Availability Groups concept was introduced the first time in S ...

  8. 如何限制服务器sql内存占用,如何在 SQL Server 中使用配置选项调整内存使用量

    更多信息 您可以使用最小服务器内存和最大服务器内存配置选项来设置 SQL Server 数据库引擎使用的内存(缓冲池)量的上下限.在设置最小服务器内存和最大服务器内存选项之前,请查阅以下 Micros ...

  9. SQL 内部联接 – 如何在 SQL 和 MySQL 中联接 3 个表

    使用数据库时,可能需要将几个不同表中的数据放在一起.本文将向您展示如何操作. 我已经在这里和这里写了关于SQL连接的文章,但让我们先花点时间回顾一下连接是如何工作的,特别是特定于MySQL的语法. S ...

最新文章

  1. MySQL面试题 | 附答案解析(二十)
  2. 使用mybatis执行oracle存储过程
  3. centos7.6基础
  4. java ancestor_java – 家谱祖先查找算法
  5. matlab创建数组对象,MATLAB一维数组(向量)的定义
  6. tensorflow实战讨论
  7. 移动网络新漏洞影响2G 以来的所有蜂窝网络
  8. Numpy根据某一列进行排序
  9. Android扫描二维码,生成二维码
  10. Veritas Backup Exec 21还原备份
  11. fastboot 常用命令
  12. python for ArcGIS 绘制武汉市板块地图
  13. 2022质量员-土建方向-岗位技能(质量员)特种作业证考试题库及模拟考试
  14. 软键盘怎么打开,软键盘怎么调出来
  15. 通达oa显示服务器错误,服务器监控
  16. 自动表单生成工具说明(后端、桌面、web、移动端)
  17. 《数字逻辑设计与计算机组成》一 第3章 3.1 简介
  18. FileWriter学习
  19. 图形编辑器——Graph Editor(树图必备)
  20. 云思智学获得2021年度“育见美好·机构创新服务奖”

热门文章

  1. vue3安装_Vue 3.0正式发布了!
  2. c语言的课本答案,c语言课本试题答案
  3. java导入excel数据到mysql_java的poi技术读取Excel数据到MySQL
  4. 软件质量与测试 黑盒测试
  5. 第十四届华中科技大学程序设计竞赛--J Various Tree
  6. sort函数用于vector向量的排序
  7. 一、app更新提示后台接口开发-(2)数据库表设计
  8. poj 2417 Discrete Logging
  9. [转一下]未来卫星通信发展趋势
  10. LeetCode(771)——宝石与石头(JavaScript)