sql server的sql单元测试存储过程

本文介绍了在数据库DevOps流程中,单元测试的重要性,尤其是针对SQL Server存储过程的单元测试。通过使用dbForge Unit Test工具,展示了如何创建并运行SQL Server存储过程的单元测试,以确保数据完整性并验证代码的正确性。文中通过一个SearchEmployee存储过程的例子,详细解释了单元测试的步骤和过程。
摘要由CSDN通过智能技术生成

Unit testing is an essential component of the database DevOps process. Its primary goal is to test the constituent parts of the database objects in order to identify any malfunctions or flaws early in the project. This approach allows database developers to ensure the changes they have made are verified, and the project will work properly. In our article, we will mainly focus on unit testing a stored procedure in a SQL Server database and exemplify how simple it is to conduct unit tests with the dbForge Unit Test tool.

单元测试是数据库DevOps流程的重要组成部分。 其主要目标是测试数据库对象的组成部分,以便在项目早期发现任何故障或缺陷。 这种方法使数据库开发人员可以确保验证他们所做的更改,并且项目将正常运行。 在本文中,我们将主要集中于对SQL Server数据库中的存储过程进行单元测试,并举例说明使用dbForge单元测试工具进行单元测试有多么简单。

Previously, we discussed the process of creating a SQL Server database for a recruitment service.

之前,我们讨论了为招聘服务创建SQL Server数据库的过程

Image for post
Img.1. The database schema for a recruitment service
图1。 招聘服务的数据库架构

As shown above, the database contains the following entities:

如上所示,数据库包含以下实体:

  • Employee

    雇员
  • Company

    公司
  • Position

    位置
  • Project

    项目
  • Skill

    技能

Nonetheless, in the series of articles, we somehow overlooked a crucial aspect of unit testing. So now, I suggest we have a closer look at this method and exemplify it by implementing the SearchEmployee stored procedure for an employee search based on certain skills. To ensure data integrity, we should add a unique constraint on the Skill table as follows:

但是,在系列文章中,我们以某种方式忽略了单元测试的关键方面。 因此,现在,我建议我们仔细研究此方法,并通过为基于某些技能的员工搜索实现SearchEmployee存储过程来举例说明。 为了确保数据完整性,我们应该在Skill表上添加唯一约束,如下所示:

ALTER TABLE [dbo].[Skill] ADD CONSTRAINT UniqueSkillName UNIQUE(SkillName);

However, before doing that, make sure the data in the SkillName field doesn’t contain any duplicate entries using the following query:

但是,在执行此操作之前,请使用以下查询确保SkillName字段中的数据不包含任何重复的条目:

SELECT 
[SkillName]
FROM [JobEmpl].[dbo].[Skill]
GROUP BY [SkillName]
HAVING COUNT(*) > 1;

Supposing you have duplicate entries, you will need to normalize all records to unique values for the SkillName field relative to one another.

假设您有重复的条目,则需要将所有记录标准化为SkillName字段相对于彼此的唯一值。

Okay, one point completed: we have created a uniqueness constraint in the names of the skills.

好的,一点已经完成:我们在技能名称中创建了唯一性约束。

Now, it’s time to implement the SearchEmployee stored procedure, as shown below:

现在,是时候实现SearchEmployee存储过程了,如下所示:

CREATE PROCEDURE [dbo].[SearchEmployee]
@SkillList NVARCHAR(MAX),
@CountNotSkill INT = 1
AS
BEGIN
	SET NOCOUNT ON;


	DECLARE @count_skills INT;


	SELECT
		[value] INTO #tbl_skill_tmp
	FROM STRING_SPLIT(@SkillList, N';');


	SELECT
		s.[SkillID]
	   ,s.[SkillName] INTO #tbl_skill
	FROM #tbl_skill_tmp AS tt
	INNER JOIN [dbo].[Skill] AS s
		ON s.[SkillName] = tt.[value];


	SET @count_skills = (SELECT
			COUNT(*)
		FROM #tbl_skill);


	SELECT
		jh.*
	   ,p.[ProjectName]
	   ,p.[Description] AS [ProjectDescription]
	   ,ts.* INTO #tbl_res0
	FROM [dbo].[JobHistory] AS jh
	INNER JOIN [dbo].[Project] AS p
		ON p.[ProjectID] = jh.[ProjectID]
	INNER JOIN [dbo].[ProjectSkill] AS ps
		ON ps.[ProjectID] = p.[ProjectID]
	INNER JOIN #tbl_skill AS ts
		ON ps.[SkillID] = ts.[SkillID];


	SELECT
		[EmployeeID]
	   ,[SkillID]
	   ,MIN([SkillName]) AS [SkillName]
	   ,SUM(DATEDIFF(DAY, [StartDate], COALESCE([FinishDate], GETDATE()))) AS [Days]
	   ,MIN([StartDate]) AS [StartDate]
	   ,MAX(COALESCE([FinishDate], GETDATE())) AS [FinishDate] INTO #tbl_res
	FROM #tbl_res0
	GROUP BY [SkillID]
			,[EmployeeID];


	SELECT
		emp.[EmployeeID]
	   ,emp.[LastName]
	   ,emp.[FirstName]
	   ,r.[SkillID]
	   ,r.[SkillName]
	   ,r.[StartDate]
	   ,r.[FinishDate]
	   ,r.[Days] / 365 AS [Years]
	   ,(r.[Days] - (r.[Days] / 365) * 365) / 30 AS [Months]
	   ,r.[Days] - (r.[Days] / 365) * 365 - ((r.[Days] - (r.[Days] / 365) * 365) / 30) * 30 AS [Days] INTO #tbl_res2
	FROM #tbl_res AS r
	INNER JOIN [dbo].[Employee] AS emp
		ON emp.[EmployeeID] = r.[EmployeeID];


	SELECT
		[EmployeeID]
	   ,[LastName]
	   ,[FirstName] INTO #tbl_empl
	FROM #tbl_res2;


	SELECT
		ts.[SkillID]
	   ,te.[EmployeeID]
	   ,ts.[SkillName]
	   ,te.[LastName]
	   ,te.[FirstName] INTO #tbl_skill_empl
	FROM #tbl_skill AS ts
	CROSS JOIN #tbl_empl AS te;


	SELECT
		tse.[EmployeeID]
	   ,tse.[LastName]
	   ,tse.[FirstName]
	   ,tse.[SkillID]
	   ,tse.[SkillName]
	   ,tr2.[StartDate]
	   ,tr2.[FinishDate]
	   ,tr2.[Years]
	   ,tr2.[Months]
	   ,tr2.[Days] INTO #tbl_res3
	FROM #tbl_skill_empl AS tse
	LEFT OUTER JOIN #tbl_res2 AS tr2
		ON tse.[SkillID] = tr2.[SkillID]
			AND tse.[EmployeeID] = tr2.[EmployeeID];


	SELECT
		[EmployeeID] INTO #tbl_empl_res
	FROM (SELECT
			[EmployeeID]
		   ,[SkillID]
		FROM #tbl_res3
		WHERE [Months] >= 6 OR [Years]>=1
		GROUP BY [EmployeeID]
				,[SkillID]) AS t
	GROUP BY [EmployeeID]
	HAVING COUNT(*) >= @count_skills - @CountNotSkill;


	SELECT
		tr2.[EmployeeID],
		tr2.[LastName],
		tr2.[FirstName],
		tr2.[SkillID],
		tr2.[SkillName],
		tr2.[StartDate],
		tr2.[FinishDate],
		tr2.[Years],
		tr2.[Months],
		tr2.[Days]
	FROM #tbl_empl_res AS ter
	INNER JOIN #tbl_res2 AS tr2
		ON ter.[EmployeeID] = tr2.[EmployeeID];


	SELECT
		tr2.[EmployeeID],
		tr2.[LastName],
	    tr2.[FirstName],
	    tr0.[CompanyID],
		(SELECT TOP(1) com.[CompanyName] FROM [dbo].[Company] AS com WHERE com.[CompanyID]=tr0.[CompanyID]) AS [CompanyName],
		tr0.[PositionID],
		(SELECT TOP(1) p.[PositionName] FROM [dbo].[Position] AS p WHERE p.[PositionID]=tr0.[PositionID]) AS [PositionName],
		tr0.[ProjectID],
		tr0.[StartDate],
		tr0.[FinishDate],
		tr0.[Description],
		tr0.[ProjectName],
		tr0.[ProjectDescription],
		tr0.[SkillID],
		tr0.[SkillName],
		tr0.[Achievements],
		tr0.[ReasonsForLeavingTheProject],
		tr0.[ReasonsForLeavingTheCompany]
	FROM #tbl_res2 AS tr2
	INNER JOIN #tbl_res0 AS tr0
		ON tr0.[EmployeeID] = tr2.[EmployeeID]
	INNER JOIN #tbl_skill AS ts
		ON ts.[SkillID] = tr0.[SkillID];


	DROP TABLE #tbl_skill_tmp;
	DROP TABLE #tbl_skill;
	DROP TABLE #tbl_res;
	DROP TABLE #tbl_res2;
	DROP TABLE #tbl_empl;
	DROP TABLE #tbl_skill_empl;
	DROP TABLE #tbl_res3;
	DROP TABLE #tbl_empl_res;
	DROP TABLE #tbl_res0;
END
GO

Why not examine the work of the SearchEmployee stored procedure in greater detail?

为什么不更详细地检查SearchEmployee存储过程的工作?

For starters, it has two input parameters:

对于初学者,它具有两个输入参数:

  1. @SkillList is the list of skills, separated by semicolons.

    @SkillList是技能列表,以分号分隔。
  2. @CountNotSkill indicates the number of skills that can be absent (1 by default).

    @CountNotSkill指示可以缺少的技能数(默认为1)。

Let’s now move on to the body of the SearchEmployee stored procedure:

现在,让我们转到SearchEmployee存储过程的主体:

  1. First, we define the variable @count_skills that is used to count the number of skills found in the database that correspond to the reported number in the input parameter @SkillList.

    首先,我们定义变量@count_skills,该变量用于对数据库中发现的与输入参数@SkillList中报告的数字相对应的技能数进行计数。
  2. Next, the @SkillList string is transformed into the temporary table #tbl_skill_tmp with the built-in function STRING_SPLIT.

    接下来,使用内置函数STRING_SPLIT将@SkillList字符串转换为临时表#tbl_skill_tmp。

  3. Then, all the suitable skills from the Skill table are found and placed into a new temporary table named #tbl_skill_tmp.

    然后,从“技能”表中找到所有合适的技能,并将其放置在名为#tbl_skill_tmp的新临时表中。
  4. After that, @count skills is counted in accordance with par.1.

    之后,@ count技能将根据参数1进行计数。
  5. Following that, the necessary information on the project (Project table) and the job history (JobHistory table) is collected based on the set skills; the result goes to a temporary table called #tbl_skill_tmp.

    然后,根据设置的技能,收集有关项目(项目表)和工作历史(作业历史表)的必要信息; 结果进入一个名为#tbl_skill_tmp的临时表。
  6. Next, the information obtained in par. 5 is grouped according to the identifiers of skill and employee, and the result goes to the temporary table #tbl_res.

    接下来,获取在参数中获得的信息。 根据技能和雇员的标识符对图5进行分组,结果进入临时表#tbl_res。
  7. Further on, the information obtained in par. 6 is combined with the Employee table so as to get the employees’ details (first and last name), and the result goes to the temporary table #tbl_res2. The query also counts how long each skill has been applied in years, months, and days to make the subsequent analysis more convenient.

    进一步,获得了在标准杆中获得的信息。 将6与Employee表组合在一起,以获取雇员的详细信息(名字和姓氏),然后结果进入临时表#tbl_res2。 该查询还计算了在数年,数月和数天内每种技能的应用时间,以使后续分析更加方便。
  8. After that, the information on the employees is retrieved from the result in par.7, and the final result is placed into the temporary table #tbl_empl.

    此后,从参数7中的结果中检索有关雇员的信息,并将最终结果放入临时表#tbl_empl中。
  9. Then, the Cartesian product of the tables #tbl_skill and #tbl_empl is made, and the result is put into the temporary table #tbl_skill_empl.

    然后,制作表#tbl_skill和#tbl_empl的笛卡尔积,并将结果放入临时表#tbl_skill_empl中。
  10. Next, a temporary table named #tbl_res3 is created, it includes the product of two temporary tables #tbl_skill_empl and #tbl_res2 where each pair employee and skill has matching information obtained in par.7.

    接下来,创建一个名为#tbl_res3的临时表,它包含两个临时表#tbl_skill_empl和#tbl_res2的乘积,其中每个员工和技能对都具有在参数7中获得的匹配信息。
  11. Then, the employee identifiers that comply with the input parameters are collected into the temporary table #tbl_empl_res. At this, the skill is considered to be valid if it has been used for at least 6 months.

    然后,将符合输入参数的员工标识符收集到临时表#tbl_empl_res中。 在此情况下,如果该技能已使用了至少6个月,则认为该技能有效。
  12. Next, follows the resulting output of employees and their skills with the time of their use measured in years, months, and days, as well as the start and end date of their application.

    接下来,跟踪雇员及其技能的输出结果,以及使用时间(以年,月,日为单位)以及其开始和结束日期。
  13. You will then see a detailed summary of the employee’s history regarding the skills we are interested in.

    然后,您将看到有关我们感兴趣的技能的员工历史的详细摘要。
  14. In the end, we drop all the temporary tables created in this stored procedure.

    最后,我们删除在此存储过程中创建的所有临时表。

After the above-mentioned steps, we can extract the names of the employees who are competent in C# and T-SQL languages as well as the ASP.NET technology on the condition that there can be maximum one lacking skill, as shown below:

完成上述步骤后,我们可以提取出能够使用C#和T-SQL语言以及ASP.NET技术胜任的员工的姓名,但前提是最多只能缺少一种技能,如下所示:

EXEC [dbo].[SearchEmployee] @SkillList = N'C#;T-SQL;ASP.NET'
,@CountNotSkill = 1;

创建并运行存储过程SQL Server单元测试 (Create and run a SQL Server Unit Test of the stored procedure)

To simplify unit testing, this stored procedure should have been divided into two: the first one to output the main information and the second one to output the details of the found employees’ history. Yet, for ease of understanding, we are going to show how to apply unit-testing for the stored procedure.

为了简化单元测试,此存储过程应该分为两部分:第一个存储主要信息,第二个输出所找到员工的历史记录的详细信息。 但是,为了便于理解,我们将展示如何对存储过程进行单元测试。

As for the tool we are going to apply: it is the Unit Test tool, which is built-in SSMS and is also a part of the dbForge Studio for SQL Server.

至于我们将要应用的工具:它是单元测试工具,它是内置的SSMS,并且是dbForge Studio for SQL Server的一部分

Let’s have a look at the tool’s functionality in SSMS.

让我们看一下SSMS中该工具的功能。

Right-click on the JobEmpl database and in the drop-down list, select Unit Test\”Install Test Framework…”:

右键单击JobEmpl数据库,然后在下拉列表中选择Unit Test \“ Install Test Framework ...”:

Image for post
Img.2. Starting the installation of Test Framework
图2。 开始安装测试框架

Similarly, the menu can be called by right-clicking any node inside the JobEmpl database.

同样,可以通过右键单击JobEmpl数据库内的任何节点来调用菜单。

Following that, make sure the server and the database are correct and click “Install”:

然后,确保服务器和数据库正确,然后单击“安装”:

Image for post
Img.3. Installing Test Framework
图3。 安装测试框架

The process of installation goes as follows:

安装过程如下:

Image for post
Img.4. The Test Framework installation process
图4。 测试框架的安装过程

At the end of the installation process, you will receive a completion message. Click the “Finish” button:

在安装过程结束时,您将收到一条完成消息。 点击“完成”按钮:

Image for post
Img.5. The successful completion of the Test Framework installation
图5。 成功完成测试框架安装

Take notice of the JobEmpl database. Below, you can see that the tSQLt objects (tables, views, functions, and stored procedures) have been created:

注意JobEmpl数据库。 在下面,您可以看到已经创建了tSQLt对象(表,视图,函数和存储过程):

Image for post
Img.5–1. Created tSQLt objects (part 1)
图5-1。 创建的tSQLt对象(第1部分)
Image for post
Img.5–2. Created tSQLt objects (part 2)
图5–2。 创建的tSQLt对象(第2部分)

Next, to create a test, right-click on the JobEmpl database and select the Unit Test\” Add New Test…” command:

接下来,要创建测试,请右键单击JobEmpl数据库,然后选择Unit Test \“ Add New Test…”命令:

Image for post
Img.6. The creation of a new unit test
图6。 创建一个新的单元测试

We now need to customize the settings for the new test named UT_SearchEmployee_Exception and click “Add Test”:

现在,我们需要自定义名为UT_SearchEmployee_Exception的新测试的设置,然后单击“添加测试”:

Image for post
Img.7. Customizing the settings for the created test
图7。 自定义创建的测试的设置

At the end of the test creation, an information window appears. Click the “Finish” button:

在测试创建结束时,将显示一个信息窗口。 点击“完成”按钮:

Image for post
Img.8. The successful completion of test creation
图8。 成功完成测试创建

You will then see a new tab in SSMS with the following code:

然后,您将在SSMS中看到一个带有以下代码的新标签:

-- Comments here are associated with the test. 
-- For test case examples, see: http://tsqlt.org/user-guide/tsqlt-tutorial/ ALTER PROCEDURE CL1.[test UT_SearchEmployee_Exception]
AS
BEGIN
--Assemble
-- This section is for code that sets up the environment. It often
-- contains calls to methods such as tSQLt.FakeTable and tSQLt.SpyProcedure
-- along with INSERTs of relevant data.
-- For more information, see http://tsqlt.org/user-guide/isolating-dependencies/ --Act
-- Execute the code under test like a stored procedure, function or view
-- and capture the results in variables or tables. --Assert
-- Compare the expected and actual values, or call tSQLt.Fail in an IF statement.
-- Available Asserts: tSQLt.AssertEquals, tSQLt.AssertEqualsString, tSQLt.AssertEqualsTable
-- For a complete list, see: http://tsqlt.org/user-guide/assertions/ EXEC tSQLt.Fail 'TODO:Implement this test.' END;

Judging by the links, the tool has several built-in functions (tSQLt Framework) that have a bunch of capabilities: with their help, you can test different database objects for different conditions. Let’s consider some examples: 1) You can check if the data in the two tables match. 2) You can check if a certain object is in the database (if it is there, then the test runs successfully, if not — it fails), etc.

从链接的角度来看,该工具具有多个内置功能(tSQLt Framework),这些功能具有很多功能:借助它们的帮助,您可以针对不同的条件测试不同的数据库对象。 让我们考虑一些示例:1)您可以检查两个表中的数据是否匹配。 2)您可以检查数据库中是否存在某个对象(如果存在,则测试成功运行,否则,测试将失败,失败),等等。

Alas, it’s not possible to catch multiple outputs in T-SQL (a couple of sets). As a rule, this is carried out in .NET, which is a safe place for creating complicated tests. Lately, there has been a tendency to mostly conduct tests at the .NET level for MS SQL Server.

las,不可能在T-SQL(几个集合)中捕获多个输出。 通常,这是在.NET中执行的,这是创建复杂测试的安全场所。 最近,有一种趋势是主要在.NET级别对MS SQL Server进行测试。

Anyway, let’s get back to T-SQL.

无论如何,让我们回到T-SQL。

For simplicity’s sake, we comment out the output of detailed information in the stored procedure, that is, we comment out a query at the end of SearchEmployee:

为了简单起见,我们在存储过程中注释掉详细信息的输出,也就是说,我们在SearchEmployee的末尾注释掉一个查询:

SELECT
		tr2.[EmployeeID],
		tr2.[LastName],
	    tr2.[FirstName],
	    tr0.[CompanyID],
		(SELECT TOP(1) com.[CompanyName] FROM [dbo].[Company] AS com WHERE com.[CompanyID]=tr0.[CompanyID]) AS [CompanyName],
		tr0.[PositionID],
		(SELECT TOP(1) p.[PositionName] FROM [dbo].[Position] AS p WHERE p.[PositionID]=tr0.[PositionID]) AS [PositionName],
		tr0.[ProjectID],
		tr0.[StartDate],
		tr0.[FinishDate],
		tr0.[Description],
		tr0.[ProjectName],
		tr0.[ProjectDescription],
		tr0.[SkillID],
		tr0.[SkillName],
		tr0.[Achievements],
		tr0.[ReasonsForLeavingTheProject],
		tr0.[ReasonsForLeavingTheCompany]
	FROM #tbl_res2 AS tr2
	INNER JOIN #tbl_res0 AS tr0
		ON tr0.[EmployeeID] = tr2.[EmployeeID]
	INNER JOIN #tbl_skill AS ts
		ON ts.[SkillID] = tr0.[SkillID];

In our case, the test is rather simple, and it is going to check the following rule: there must be data, otherwise, it will output a message that the skills may have been incorrect, and the stored procedure does not function the way it should.

在我们的例子中,测试非常简单,它将检查以下规则:必须有数据,否则,它将输出一条消息,提示技能可能不正确,并且存储过程无法正常运行应该。

A failure to implement the rule indicates that either the data is absent and has to be searched based on different criteria, or the criteria have been defined incorrectly and have to be fixed. It can also mean that the stored procedure itself fails to operate properly.

未能执行规则表示数据不存在,必须根据不同标准进行搜索,或者标准定义不正确且必须进行修复。 这也可能意味着存储过程本身无法正常运行。

So, we return to the code we generated earlier and change it as follows:

因此,我们返回到我们之前生成的代码,并对其进行如下更改:

-- Comments here are associated with the test. 
-- For test case examples, see: http://tsqlt.org/user-guide/tsqlt-tutorial/
ALTER PROCEDURE CL1.[test UT_SearchEmployee_Exception]
AS
BEGIN
CREATE TABLE #tbl ([EmployeeID] INT, [LastName] NVARCHAR(255), [FirstName] NVARCHAR(255),
[SkillID] INT, [SkillName] NVARCHAR(255), [StartDate] DATETIME, [FinishDate] DATETIME,
[Years] INT, [Months] INT, [Days] INT); INSERT INTO #tbl
EXEC [dbo].[SearchEmployee] @SkillList = N'programming'
,@CountNotSkill = 1; IF(NOT EXISTS(SELECT TOP(1) 1 FROM #tbl))
EXEC tSQLt.Fail 'Nothing found. Check input parameters and stored procedure code'; DROP TABLE #tbl;
END;

Now, let’s do one more right-click on the JobEmpl database and in the drop-down menu, select the Unit Test\” View Test List” command:

现在,让我们在JobEmpl数据库上再单击鼠标右键,然后在下拉菜单中选择“单元测试\“查看测试列表””命令:

Image for post
Img.9. Calling the View Test List command
图9。 调用查看测试列表命令

After that, we choose the test we need and run it:

之后,我们选择所需的测试并运行它:

Image for post
Img.10. Running the given test
图10。 运行给定的测试

As we can see below, the test was not successful:

如下所示,测试未成功:

Image for post
Img.11. Running the unit test resulted in an error
图11。 运行单元测试导致错误

It is important to stress that you can select multiple unit tests and launch them all, or just several of them. If necessary, you can create and delete a test. Here, we will open the selected test by clicking the “Open Test” command:

需要强调的是,您可以选择多个单元测试并将其全部启动,也可以仅启动其中几个。 如有必要,您可以创建和删除测试。 在这里,我们将通过单击“打开测试”命令来打开所选的测试:

Image for post
Img.12. Selecting a command to open the unit test
图12。 选择一个命令以打开单元测试

We want to change the code to the following:

我们要将代码更改为以下内容:

-- Comments here are associated with the test. 
-- For test case examples, see: http://tsqlt.org/user-guide/tsqlt-tutorial/
ALTER PROCEDURE CL1.[test UT_SearchEmployee_Exception]
AS
BEGIN
CREATE TABLE #tbl ([EmployeeID] INT, [LastName] NVARCHAR(255), [FirstName] NVARCHAR(255),
[SkillID] INT, [SkillName] NVARCHAR(255), [StartDate] DATETIME, [FinishDate] DATETIME,
[Years] INT, [Months] INT, [Days] INT); INSERT INTO #tbl
EXEC [dbo].[SearchEmployee] @SkillList = N'C#;T-SQL;ASP.NET'
,@CountNotSkill = 1; IF(NOT EXISTS(SELECT TOP(1) 1 FROM #tbl))
EXEC tSQLt.Fail 'Nothing found. Check input parameters and stored procedure code'; DROP TABLE #tbl;
END;

Next, let’s run the test again:

接下来,让我们再次运行测试:

Image for post
Img.13. The successful completion of a unit test
图13。 成功完成单元测试

As a result, the test ran successfully. The error simply occurred because the “programming” skill was not in the database, and we had to further detail the skill.

结果,测试成功运行。 该错误仅是由于“编程”技能不在数据库中而发生的,因此我们不得不进一步详细说明该技能。

As well as that, we can rename the test class and the test itself and update the information on the tests:

除此之外,我们可以重命名测试类和测试本身,并更新有关测试的信息:

Image for post
Img.14. The possibility to rename and update the test class information
图14。 重命名和更新测试类信息的可能性

You can also run tests and open changes at the bottom of the window in Test Result:

您还可以运行测试并在“测试结果”窗口的底部打开更改:

Image for post
Img.15. The Test Result functionality
图15。 测试结果功能

Eventually, you can cover most or even the whole functionality of the created solution with the help of unit tests. The bottom line is that unit tests are part of the DevOps fundamental principles as they play one of the key roles in this automation process. If you strive to speed up and secure database release, you can apply one of several solutions for DevOps automation, such as DevOps Automation for SQL Server.

最终,您可以在单元测试的帮助下涵盖所创建解决方案的大部分甚至全部功能。 最重要的是,单元测试是DevOps基本原理的一部分,因为它们在此自动化过程中扮演着关键角色之一。 如果您努力加快速度并确保数据库的发布安全,则可以应用DevOps自动化的多种解决方案之一,例如SQL Server的DevOps Automation

Originally published at https://blog.devart.com on August 31, 2020.

最初于2020年8月31日https://blog.devart.com发布

翻译自: https://towardsdatascience.com/sql-unit-testing-stored-procedure-for-sql-server-9565d86ac458

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值