SQL Server道一下大家是怎开数据库单元测试(Database Unit Test)的

笔者水平有限,如发生错误或纰漏,请指出,谢谢。

背景介绍

日前在集团于做release在此以前的regression,把各类feature分支merge回master之后发现DB的单元测试出现了20大四个败的test
cases。在此以前没有怎么开过DB的单元测试,正好借这会了解一下状DB单元测试的流程。

这篇博文中率先介绍一下每当大家的特定类型场景中凡是怎搭建DB
单元测试框架的,然后推一个简便的例证,从头到尾在visual
studio中创立一个粗略的单元测试工程。

咱俩付出的活使用的数据库也Sql
Server,总共有400大抵张表,2000大抵独存储过程,每个存储过程都一定给以代码中的一个功用函数。代码中之每个复杂的意义函数都可通过描写单元测试来在得水平及保证代码质料,存储过程为如此。代码中的UT难点在于解耦,也就是将相互牵连在一起的代码互相分离开来,各个击破,例如A函数需要B函数提供的数码,测试A函数的时光我们只想测试A函数,不牵挂调用B,那时候就用大家自己提供B函数生成的多寡。这名mock。

于做DB单元测试的上,存储过程所下的数量比独特,都是持久化在数据库表中的,2000四只存储过程增删改查400大抵独表达,大家用把这个发明底数码吧每个存储过程做隔离,假若测试用例使用的多少交互关联,恐怕会天下大乱,因为当相似意况下,单元测试用例的周转顺序都是轻易的,假诺单元测试使用的数量有关统一,很有或有限不善运行结果为是即兴的(可是来同等栽形式可固定case执行各种,我在末的事例中举办表达),大家这一次的20多独破产的cases就发出这种由造成的,两大机械及跑起之结果未相同,有的成,有的失利。

流动:有关单元测试的定义,见其余一篇帖子,单元测试有毒

这就是说问题便来了,怎样才能够召开多少的隔断呢?说一下大家的方案。

未雨绸缪数据

咱俩成立了一个条件的数据库,做出一个备份,叫做base.bak,这些本子相比低,比如是2.8,这其间含有了有的测试的骨干数据。然后我们创立了其它一个preparation的工,用于把base.bak升级至当前release版本,例如,当前release的本也2.18。那多少个工程以为测试了提拔的流水线。升级成后,把此数据库在本土做一个备份release_2_18.bak。好了,数据还备好了。

测试需要小心的中央

季个函数

对微软的此DB
UT测试框架,有四独函数需要将懂,因为这可能影响您的测试结果:

[ClassInitialize]
public static void ClassInitialize(TestContext testContext)
{
    ...
}
[ClassCleanup]
public static void ClassCleanup()
{
   ...
}
[TestInitialize()]
public void TestInitialize()
{
   ...
}
[TestCleanup()]
public void TestCleanup()
{            
   ...
}
  • 顾名思义,ClassInitialize() 是在每个类开头化的早晚给调用的
  • ClassCleanup()
    凡是于近似截至之时,也即是一个接近有的case跑了的上给调用的
  • TestInitialize() 是在每个case跑此前受调用的。
  • TestCleanup() 是在每个case调用之后让调用的。

对么?粗体的当即句话不针对,其它是针对之。

测试用例的运转是无序的,包含七只类似的意况。

圈下面测试用例的底内容情状你就精通了:

AssemblyInitialize
TestClass1: ClassInitialize
TestClass1: TestInitialize
TestClass1: MyTestCase1
TestClass1: TestCleanup
TestClass2: ClassInitialize
TestClass2: TestInitialize
TestClass2: MyTestCase2
TestClass2: TestCleanup
TestClass1: ClassCleanup
TestClass2: ClassCleanup
AssemblyCleanup

ClassCleanup() 并无代表TestClass1ClassCleanup
在是近乎的最终一个case跑了之后被当下调用!事实上,它会合等所有case都为周转了事后,同TestClass2
ClassCleanup 一片执行。

切切实实原因看是帖子,How to run ClassCleanup (MSTest) after each class
with
test?

三个Action

要看下边的一个事例:

[TestMethod()]
public void Test_GetBasicRevenueByName()
{
    SqlDatabaseTestActions testActions = this.SqlTest1Data;
    // Execute the pre-test script
    // 
    System.Diagnostics.Trace.WriteLineIf((testActions.PretestAction != null), "Executing pre-test script...");
    SqlExecutionResult[] pretestResults = TestService.Execute(this.PrivilegedContext, this.PrivilegedContext, testActions.PretestAction);
    // Execute the test script
    // 
    System.Diagnostics.Trace.WriteLineIf((testActions.TestAction != null), "Executing test script...");
    SqlExecutionResult[] testResults = TestService.Execute(this.ExecutionContext, this.PrivilegedContext, testActions.TestAction);
    // Execute the post-test script
    // 
    System.Diagnostics.Trace.WriteLineIf((testActions.PosttestAction != null), "Executing post-test script...");
    SqlExecutionResult[] posttestResults = TestService.Execute(this.PrivilegedContext, this.PrivilegedContext, testActions.PosttestAction);
}

每个测试用例中还会合爆发三独action,这六个Action的用处如下:

  • PretestAction做的凡测试前的备工作,具体经过中但是当每个特定的case插入或更新测试需要的多少。
  • TestAction为调用存储过程进展测试,将实际结果及预期结果举办对比。
  • PosttestAction做的凡测试好后底清理工作,这里可以对PretestAction中的插入或者更新的多少开展回滚,复苏起来环境

最终之斯PosttestAction为咱的数目隔离提供了千篇一律栽情势,所谓恢复生机起来环境之意是实践一个case从前和下数据库中之多少全同。

此出个问题,在PretestAction中举办数量插入还于好恢复生机,假使是抹和更新为?这即待而记录下删除的跟翻新前的多寡。太费事了。即便您的网性能充裕好,或者对运行UT的工夫不曾要求,可以据此其它一种艺术:restore
DB
。前面不是说罢了么,我们当数据库升级之后开了一个备份,我们以这边用它们。在何地举办restoreDB?对,在TestCleanup()
中进行。

[TestInitialize()]
public void TestCleanup()
{
   restoreDB();
}

总结

具体的流水线便说得了了,总结一下:

准备数据库

SQL Server 1

运行测试用例流程

SQL Server 2

数码清理的少种植模式

  • 每当PretestAction中补充加数据苏醒语句;
  • TestCleanup()中restore DB。

实例

接下去大家锲而不舍演示一下据此VS2013 + SQL Server 2012是哪做数据库UT的。

创建一个略的数据库DBUTDemo

  • 始建两摆设表。

create table EmployeeBasicInfo(
   EmployeeNo int NOT NULL primary key,
   Name nvarchar(50) NOT NULL,
   TelephoneNum varchar(50) NOT NULL  
);

create table EmployeeRevenue(
   EmployeeNo int NOT NULL primary key,
   BasicRevenue int NOT NULL,
   MealSubsidy int NULL,
   Bonus int NULL,
   foreign key(EmployeeNo) references EmployeeBasicInfo(EmployeeNo)  
);
  • 创制一个囤积过程

create procedure GetBasicRevenueByName(@name nvarchar(50))  
as
begin
    select bi.Name,r.BasicRevenue from EmployeeRevenue r join EmployeeBasicInfo bi on r.EmployeeNo = bi.EmployeeNo where bi.Name = @name
end

创建UT工程

  • 点击File->New->Project…

SQL Server 3

  • 选择Unit Test Project,输入工程称为,选用创制路径,点击OK

SQL Server 4

加上一个类

  • 右键DBUTDemo->Add->New Item…
    SQL Server 5
    选择SQL Server Unit Test,输入名字,点击Add。
    SQL Server 6
  • 第一差添加数据库测试类需要配备数据库:
    点击New Connection

SQL Server 7

输入Server name,选拔大家才创造的数据库DBUTDemo,点击Test
Connection
。虽然成功碰面弹来对话框。连续两赖点击OK。数据库配置就好了。

SQL Server 8

制造三独Actions

点击Click here to
create
来创制TestAction,点击后察觉多了一个resx文件。

SQL Server 9

输入上面的测试代码:

declare @return_value  int,
        @name  nvarchar(50)

EXEC    @return_value = [dbo].[GetBasicRevenueByName]
        @name = N'three zhang'

SELECT  'Return Value' = @return_value

通下创立此外两单Action:
SQL Server 10

独家输入如下代码:

insert into EmployeeBasicInfo values(1,'three zhang',    '16625344257')
insert into EmployeeBasicInfo values(2,'four li',   '16625344258')
insert into EmployeeBasicInfo values(3,'simon', '16625344259')
insert into EmployeeBasicInfo values(4,'jack',  '16625344250')

insert into EmployeeRevenue values(1    ,30000  ,500    ,20000)
insert into EmployeeRevenue values(2    ,28000  ,500    ,19000)
insert into EmployeeRevenue values(3    ,27000  ,500    ,10000)
insert into EmployeeRevenue values(4    ,26000  ,500    ,20000)

delete from EmployeeRevenue
delete from EmployeeBasicInfo

SQL Server 11

说到底补充加测试条件

SQL Server 12
咱补充加了少数只测试条件,值好于性界面被修改:
SQL Server,首先单测试条件是于回到结果集1际遇,第一履行第二排列的期望值吗30000,也即便是three
zhang的主导工资吧30000。

SQL Server 13

亚只测试条件测试结果集1非空。

SQL Server 14

编译,运行

编译成功后,打开Test Explorer,run我们才创设的case,测试通过。
SQL Server 15

Ordered Test

末段说生数据库测试用例假诺要一定的依次该怎么处置,微软资了一致栽测试用例类型叫做Ordered
Test:
SQL Server 16
这种case是管几乎独case集合成为了一个,可以自己选得周转的便的case,自己指定顺序。因为各类固定了,这个cases中利用的数目就是是可控的,由此在一个ordered
case中之多少个case可以合使用一些数据,我们可以用数据隔离的单位由于单个case变为几独case甚至一个看似中之享有cases。
SQL Server 17

相关文章