演练:为独立开发环境建立基线
在本演练中,已经创建了一个数据库项目并将其置于版本控制之下。 该数据库项目包含的架构定义与成品服务器的架构定义相匹配。 在该数据库项目的开发工作开始之前,要通过设置数据库单元测试、定义数据生成计划、生成测试数据和运行这些测试来建立质量基线。 测试运行将生成数据库并将其部署到您的独立开发环境中,用生成的数据填充数据库,并执行单元测试来报告结果。
本演练演示以下任务:
如何为独立开发环境自定义部署设置。
如何生成数据库并将其部署到独立开发环境中。
如何创建数据生成计划并对其进行自定义,以生成更真实的测试数据。
如何为数据库项目包含的存储过程定义单元测试。
如何生成测试数据以及生成和运行单元测试。
如何通过将单元测试作为解决方案的一部分置于版本控制之下,从而与开发团队共享单元测试。
系统必备
若要定义数据库单元测试并创建、修改和运行数据生成计划,您必须已安装 Visual Studio 高级专业版 或 Visual Studio 旗舰版,并且能够访问 SQL Server 2008 的 AdventureWorks2008 示例数据库(或 SQL Server 2008 R2 的 AdventureWorks2008R2 示例数据库)。 此外,还必须已经完成演练:创建独立数据库开发环境中的步骤。
为独立开发环境自定义生成设置
如果 AdvWorksSandbox 解决方案已在**“解决方案资源管理器”**中打开,则转至步骤 4。
在**“文件”菜单上,指向“打开”,然后单击“项目/解决方案”**。
将出现**“打开项目”**对话框。
单击 AdvWorksSandbox 解决方案,然后单击**“打开”**。 (此解决方案的默认位置为 My Documents\Visual Studio 2010\Projects\AdvWorksSandbox。)
AdvWorksSandbox 解决方案将在**“解决方案资源管理器”**中打开。
在**“解决方案资源管理器”**中单击“AdvWorksSandbox”节点。
在**“项目”菜单上,单击“AdvWorksSandbox 属性”**。
单击**“部署”**选项卡。
在**“配置部署设置”下拉列表中,选择“我的独立开发环境”**。
提示
为独立开发环境配置的部署设置存储在包含数据库项目的文件夹中的 .user 文件内。 .user 文件未签入到版本控制中。 通过这种设计,每位开发人员都能够为各自的独立开发环境配置设置。
单击**“目标连接”旁边的“编辑”**。
随即出现**“连接属性”**对话框。
在此对话框中可为本地独立开发环境自定义连接字符串。 推荐的过程是每个数据库开发人员均更新数据库的私有副本,以便更改不会对团队的其余成员产生不利影响。 当开发人员已对更改进行了测试并准备将其与团队共享时,他或她会通过中央版本控制系统来共享更改。 在 演练:创建独立数据库开发环境 中,设置了目标数据库名称,但未设置连接。
键入或单击要用于独立开发环境的服务器的名称。 例如,要使用本地实例,应键入 (local)。
重要事项 如果将您的隔离开发数据库部署到您在上一个演练中部署的同一个服务器上,则会出现错误。 出现错误的原因是您已创建该文件。 您可以通过更改 FileStreamDocuments.sqlfile.sql 文件中的 FILENAME 参数(或者针对 SQL Server 2008 R2 更改 FileStreamDocuments2008R2.sqlfile.sql)来更正此错误。 将该参数更改为与以下代码匹配:FILENAME = '$(DefaultDataPath)SandboxDocuments-IDE')
单击要用来连接数据库服务器的身份验证类型。
默认情况下会指定 Windows 身份验证。
单击**“确定”**。
目标连接会显示连接信息。
在**“文件”菜单上,单击“保存选定项”**,以保存对数据库项目属性的更改。
生成数据库并将其部署到独立开发环境中
在**“生成”菜单上,单击“生成解决方案”**。
将生成数据库项目,而且结果会显示在**“输出”**窗口中。
在**“解决方案资源管理器”**中单击“AdvWorksSandbox”节点。
在**“生成”菜单上,单击“部署 ProjectName”。 还可以右击“AdvWorksSandbox”节点,再单击“部署”**。
将生成数据库项目,生成一个部署脚本,然后将该脚本部署到在数据库项目属性中指定的独立数据库开发服务器中。
接下来将要为独立开发环境生成测试数据。
生成测试数据
既然您已经拥有一个可进行开发的独立数据库,您需要可以驱动单元测试的测试数据。 首先,创建一个默认数据生成计划,然后对该计划进行自定义,使其生成更加真实的数据。 在此示例中,您仅为数据库中表和列的子集配置数据生成。 您将为“Employee”表和“StateProvince”表配置数据生成。
StateProvince 表中的原始数据不区分大小。 因此,可以使用原始数据填充独立开发数据库。
但是,应对“Employee”表的默认生成计划进行下列更改:
“Title”应为下列内容之一:Developer、Sr. Developer、Tester、Sr. Tester、Project Manager、Sales Associate 或 Sr. Sales Associate。
“BirthDate”必须至少在 18 年以前,但不能早于 1930 年 1 月 1 日。 此规范与数据库中该列的约束相匹配。
“Marital Status”必须为“M”或“S”。
“Gender”必须为“M”或“F”。
“HireDate”不得晚于当天日期,也不能早于 2000 年 1 月 1 日。
“VacationHours”应具有在 -10 到 160 这一范围内的典型分布。
“ModifiedDate”不得晚于当天日期,也不能早于 2000 年 1 月 1 日。 大多数记录都将在近期进行了更新。
“Person”表中的“AdditionalContactInfo”和“Demographics”必须来自源 AdventureWorks 数据库。
创建数据生成计划
在**“解决方案资源管理器”**中展开“AdvWorksSandbox”节点,然后单击“数据生成计划”文件夹。
在**“项目”菜单上,单击“添加新项”**。
将显示**“添加新项”**对话框。
在**“类别”列表中单击“数据生成计划”**。
在**“模板”列表中单击“数据生成计划”**。
在**“名称”中键入“AWGenPlan.dgen”,然后单击“添加”**。
将向数据库项目中添加一个名为 AWGenPlan 的数据生成计划并在编辑器中打开该计划。 数据库架构也导入数据生成计划中。
接下来,您将修改 AWGenPlan 以生成更加真实的测试数据。
将数据生成限制到相关表
右击数据生成计划,再单击**“从数据生成中排除所有表”**。
在数据生成计划中选中下列表对应的复选框:HumanResources.Employee、Person.Person、Person.CountryRegion 和 Person.StateProvince。
接下来,您将为“StateProvince”表定义数据生成计划。
为“StateProvince”表定义数据生成计划
单击数据生成计划中的**“[Person].[StateProvince]”**。
在“列详细信息”窗格中单击**“StateProvinceCode”,然后将“生成器”字段设置为“顺序数据绑定生成器”**。
此步骤表明要使用查询结果来填充此列。
在**“视图”菜单上,单击“属性窗口”**。
在**“属性”**窗口的“生成器”部分中的 Connection Information 属性中,单击在前面的过程中从中导入数据库架构的数据库所对应的连接。
此步骤指定在运行将为此列生成数据的查询时要使用的数据库连接。
在**“属性”**窗口的“生成器”部分中的 Select Query 属性中,将查询字符串设置为 SELECT [StateProvinceCode] FROM [Person].[StateProvince]。
在“列详细信息”窗格中,单击**“修改日期”**。
在**“属性”**窗口的“生成器”部分中,将 Max 属性设置为今天的日期,这是因为记录不可能已在将来的某个日期修改。
在**“属性”**窗口的“生成器”部分中,将 Min 属性设置为 1/1/2000 12:00:00 AM。 在本示例中,假定公司从 2000 年伊始便开始收集数据。
接下来,您将为“Person”表指定数据生成计划。
为“Person”表定义数据生成计划
单击数据生成计划中的**“[Person].[Person]”**。
在“列详细信息”窗格中单击**“PersonType”**,然后将“生成器”字段设置为“正则表达式”。
在**“属性”**窗口的“生成器”部分中,将 Expression 属性设置为“(GC|SP|EM|IN|VC|SC)”。
在“列详细信息”窗格中单击**“AdditionalContactInfo”,然后将“生成器”字段设置为“顺序数据绑定生成器”**。
此步骤表明要使用查询结果来填充此列。
在**“视图”菜单上,单击“属性窗口”**。
在**“属性”**窗口的“生成器”部分中的 Connection Information 属性中,单击在前面的过程中从中导入数据库架构的数据库所对应的连接。
此步骤指定在运行将为此列生成数据的查询时要使用的数据库连接。
在**“属性”**窗口的“生成器”部分中的 Query Select Query 属性中,将查询字符串设置为 SELECT * FROM [Person].[Person]。
在“列详细信息”窗格中 AdditionalContactInfo 的“生成器输出”字段中,单击**“[AdditionalContactInfo]”**。
此步骤在结果集中选择要与此列关联的列。
在“列详细信息”窗格中单击**“Demographics”,然后将“生成器”字段设置为“顺序数据绑定生成器”**。
此步骤表明要使用查询结果来填充此列。
在**“视图”菜单上,单击“属性窗口”**。
在**“属性”**窗口的“生成器”部分中的 Connection Information 属性中,单击在前面的过程中从中导入数据库架构的数据库所对应的连接。
此步骤指定在运行将为此列生成数据的查询时要使用的数据库连接。
在**“属性”**窗口的“生成器”部分中的 Query Select Query 属性中,将查询字符串设置为 SELECT * FROM [Person].[Person]。
在“列详细信息”窗格中 Demographics 的“生成器输出”字段中,单击**“[Demographics]”**。
此步骤在结果集中选择要与此列关联的列。
在“列详细信息”窗格中,单击**“修改日期”**。
在**“属性”**窗口的“生成器”部分中,将 Max 属性设置为今天的日期,这是因为记录不可能已在将来的某个日期修改。
在**“属性”**窗口的“生成器”部分中,将 Min 属性设置为 1/1/2000 12:00:00 AM。 在本示例中,假定公司从 2000 年伊始便开始收集数据。
接下来,您将为“Employee”表指定数据生成计划。
为“Employee”表定义数据生成计划
单击数据生成计划中的**“[HumanResources].[Employee]”**。
在“列详细信息”窗格中单击**“JobTitle”,然后将“生成器”字段设置为“RegularExpression”**。
在**“属性”**窗口的“生成器”部分中,将 Expression 属性设置为“(Developer|Sr\.Developer|Tester|Sr\.Tester|Project Manager|Sales Associate|Sr\.Sales Associate)”。
在“列详细信息”窗格中单击**“BirthDate”**。
默认情况下,“生成器”字段会设置为**“DateTime2”**。
在**“属性”**窗口的“生成器”部分中,将 Max 属性设置为当天日期的 18 年前(例如,10/30/1987 11:59:59 PM)。 另外,将 Min 属性设置为 1/1/1930 12:00:00 AM。
在“列详细信息”窗格中单击**“MaritalStatus”,然后将“生成器”字段设置为“RegularExpression”**。
在**“属性”**窗口的“生成器”部分中,将 Expression 属性设置为“(M|S)”。
在“列详细信息”窗格中单击**“Gender”,然后将“生成器”字段设置为“RegularExpression”**。
在**“属性”**窗口的“生成器”部分中,将 Expression 属性设置为“(M|F)”。
在“列详细信息”窗格中单击**“HireDate”**。
默认情况下,“生成器”字段会设置为“DateTime2”。
在**“属性”**窗口的“生成器”部分中,将 Max 属性设置为当天日期(例如,10/30/2006 11:59:59 PM)。 另外,将 Min 属性设置为 1/1/2000 12:00:00 AM。
在“列详细信息”窗格中单击**“VacationHours”**。
默认情况下,“生成器”字段会设置为**“SmallInt”**。
在**“属性”**窗口的“生成器”部分中,将 Distribution 属性设置为“Normal”。
在**“属性”**窗口的“生成器”部分中,将 Max 属性设置为 160 并将 Min 属性设置为 -10。
在“列详细信息”窗格中单击**“ModifiedDate”**。
默认情况下,“生成器”字段会设置为**“DateTime2”**。
在**“属性”**窗口的“生成器”部分中,将 Distribution 属性设置为“ExponentialInverse”。 另外,将 Max 属性设置为当天日期(例如,10/30/2006 11:59:59 PM)并将 Min 属性设置为 1/1/2000 12:00:00 AM。
调整要生成的行数
单击数据生成计划中的**“[Person].[CountryRegion]”**。
在**“要插入的行”**字段中键入 10。
单击数据生成计划中的**“[HumanResources].[Employee]”**。
在**“要插入的行”**字段中键入 25。
单击数据生成计划中的**“[Person].[StateProvince]”**。
在**“相关表”字段中单击“[Person].[CountryRegion]”**。
在**“相关表的比率”**字段中键入 2:1。
此步骤指定要为 [Person].[StateProvince] 表生成两倍于 [Person].[CountryRegion] 表的行数。
在**“文件”菜单上,单击“保存 AWGenPlan.dgen”**,保存对数据生成计划所做的更改。
预览数据生成和生成测试数据
如果多次运行数据生成,则 HumanResources.Employee 表包含的触发器可能会影响数据生成。 若要在自动测试运行过程中执行数据生成,必须在单元测试中禁用(稍后再启用)这些触发器。
若要在该过程中多次运行数据生成操作,则必须按照在生成数据时禁用和启用 Employee 表中的触发器过程操作。 若要仅运行一次数据生成操作,请按照验证数据生成计划的结果过程操作。
预览数据生成和生成测试数据
在**“数据”菜单上,指向“数据生成器”,然后单击“预览数据生成”**。
**“数据生成预览”**窗口随即出现,并显示将生成的数据的示例。 如果数据符合指定的条件,请继续执行下一步。 如果需要调整数据生成计划,请进行适当的更改,然后重复执行此步骤。
在**“数据”菜单上,指向“数据生成器”,然后单击“生成数据”**。
**“为目标数据库生成数据”**对话框随即出现。
在**“目标数据库”中,创建与 AdvWorksSandbox 数据库的连接,然后单击“确定”**。
当系统询问您“生成新数据前是否从表中删除现有数据?”时,请单击**“是”**。
数据是根据您的指定生成的。 生成完成时,在每一行中将出现一个绿色的选中标记,指示所有数据已成功生成。 如果未生成数据,**“错误列表”**窗口中将出现错误。
跳到名为“验证数据生成计划结果”的过程。
在生成数据时禁用和启用 Employee 表中的触发器
在生成数据之前,请打开**“数据”菜单,指向“Transact-SQL 编辑器”,然后单击“新建查询连接”**。
如果独立开发环境中的数据库已存在连接,请转到步骤 7。
单击**“新建连接”**。
随即出现**“连接属性”**对话框。
在**“服务器名称”**中,键入或单击将数据库部署到的数据库服务器的名称,如 (local)\SQLExpress。
在**“登录到服务器”中,单击“使用 Windows 身份验证”**。
在**“连接到一个数据库”中,单击“选择或输入一个数据库名”,键入“AdvWorksSandbox”,然后单击“确定”**。
已创建了连接并将其添加到了**“连接到数据库”**对话框中的列表中。
在**“连接到数据库”对话框中,单击与独立开发环境中的数据库对应的连接字符串,然后单击“确定”**。
将出现 Transact-SQL 编辑器,其中有一个到 AdvWorksSandbox 数据库的活动连接。
单击**“确定”**。
将出现 Transact-SQL 编辑器。
在 Transact-SQL 编辑器中键入以下 Transact-SQL:
DISABLE TRIGGER [HumanResources].[dEmployee] ON [HumanResources].[Employee] GO
在 Transact-SQL 编辑器工具栏上,单击**“执行 SQL”**。
在**“消息”**选项卡上,将出现以下内容:
命令成功完成。
单击包含数据生成计划的窗口。
在**“数据”菜单上,指向“数据生成器”,然后单击“预览数据生成”**。
**“数据生成预览”**窗口随即出现,并显示将生成的数据的示例。 如果数据符合指定的条件,请继续执行下一步。 如果需要调整数据生成计划,请进行适当的更改,然后重复执行此步骤。
在**“数据”菜单上,指向“数据生成器”,然后单击“生成数据”**。
**“为目标数据库生成数据”**对话框随即出现。
在**“目标数据库”中,单击到 AdvWorksSandbox 数据库的连接,然后单击“确定”**。
当系统询问您“插入新行前是否清除所选表的内容?”时,请单击**“是”**。
数据是根据您的指定生成的。 生成完成时,在每一行中将出现一个绿色的选中标记,指示所有数据已成功生成。 如果未生成数据,**“错误列表”**窗口中将出现错误。
单击 Transact-SQL 编辑器窗口。
一般而言,您将在此处重新启用触发器。 但是,为了简化数据库单元测试以便在单元测试过程中无需禁用并重新启用触发器,您将保持触发器的禁用状态。
验证数据生成计划的结果
在**“数据”菜单上,指向“Transact-SQL 编辑器”,然后单击“新建查询”**。
将出现**“连接到数据库”**对话框。
如果独立开发环境中的数据库已存在连接,请转到步骤 8。
单击**“新建连接”**。
随即出现**“连接属性”**对话框。
在**“服务器名称”**中,键入或单击将数据库部署到的数据库服务器的名称,如 (local)\SQLExpress。
在**“登录到服务器”中,单击“使用 Windows 身份验证”**。
在**“连接到一个数据库”中,单击“选择或输入一个数据库名”,键入“AdvWorksSandbox”,然后单击“确定”**。
已创建了连接并将其添加到了**“连接到数据库”**对话框中的列表中。
在**“连接到数据库”对话框中,单击与独立开发环境中的数据库对应的连接字符串,然后单击“确定”**。
将出现 Transact-SQL 编辑器,其中有一个到 AdvWorksSandbox 数据库的活动连接。
在 Transact-SQL 编辑器中键入以下内容:
SELECT * from HumanResources.Employee;
按 F5 运行查询。
将出现结果窗格,其中显示数据生成的结果。
在**“文件”菜单上,单击“关闭”**以关闭 Transact-SQL 编辑器。
接下来,定义可验证现有数据库代码的数据库单元测试。
定义单元测试
通常,您会为所有存储过程、函数和触发器定义单元测试。 在本演练中,您只定义一个单元测试作为示例。 您为 ufnLeadingZeros 函数和 dbo.uspGetManagerEmployees 存储过程定义一个测试。
ufnLeadingZeros 函数接受一个整数,并返回该整数的填充了前导零的 VARCHAR(8) 字符串表示形式。 若要测试此函数,可以传入一个值,并测试是否可以获得预期结果。
向 uspGetManagerEmployees 存储过程传递一个员工标识符,它会返回具有指定标识符的经理管理的所有员工(完整层次结构)。 由于在给定相同的种子值时数据生成器将生成相同的测试数据,因此可以知道应返回的行数。 此测试非常简单。 在实际项目中,您将要创建更详细的测试,确认返回了符合标准的员工。
创建单元测试
在**“视图”菜单上,单击“架构视图”**。
如果尚未显示**“架构视图”**,则会显示该视图。
在**“架构视图”中,依次打开“架构”文件夹、“dbo”文件夹和“可编程性”**文件夹。
右击**“函数”文件夹,再单击“创建单元测试”**。
随即出现**“创建单元测试”**对话框。
展开当前选择树,然后选中对应于函数**“dbo.ufnLeadingZeros”**的复选框。 清除对应于所选择的任何其他存储过程或函数的复选框。
提示
若要为项目建立实际基线,需要为数据库中的所有函数、存储过程和触发器创建单元测试。 本演练重点介绍一个函数来演示该过程。
在**“项目”中,单击“创建新的 Visual C# 测试项目…”**。
在**“新项目名称”中键入“AWSandboxTestProject”,然后单击“确定”**。
将创建单元测试项目,并且会显示单元测试的**“项目配置”**对话框。
在**“数据库连接”**中单击 AdvWorksSandbox 的连接。
在**“部署”中,清除“在运行测试前自动部署数据库项目”**复选框。
在**“数据库状态”中,选择“在运行单元测试前生成测试数据”**复选框。
在**“数据库状态”列表中单击“AWGenPlan.dgen”**。
如果尚未选中**“在生成测试数据前清除数据库”复选框,请选中它,然后单击“确定”**。
将创建数据库单元测试项目并将其添加到解决方案中。 此时会打开“数据库单元测试设计器”,以便您修改测试条件并创作测试。
提示
如果必须修改测试配置,请打开“测试”菜单并单击“数据库测试配置”。 将出现“项目配置”对话框,您可以更改配置。
接下来您将指定测试条件并编写测试。
为 ufnLeadingZeros 函数定义单元测试
在“数据库单元测试设计器”中的测试列表中单击**“dbo.ufnLeadingZeros”**。
验证第二个列表是否显示“Test”。
将设计器上窗格中的 Transact-SQL 语句替换为以下内容:
-- db unit test for dbo.ufnLeadingZeros DECLARE @RC VARCHAR (8), @Value INT SELECT @RC = NULL, @Value = 27 SELECT @RC = [dbo].[ufnLeadingZeros]( @Value) IF @RC <> '00000027' RAISERROR(N'ufnLeadingZero: expected "00000027" but got %s.', 16, 1, @RC) SELECT RC=@RC
在**“测试条件”窗格中,单击类型为“没有结论”的测试条件,并通过单击“删除测试条件”**(x) 将其删除。
通过在**“测试条件”窗格中的列表中单击“行数”,再单击“添加测试条件”**(+) 来添加行数测试条件。
在**“属性”**窗口中,将“行数”属性设置为 1。
如果要强制使测试失败,请将 @Value 从 27 更改为其他值。
现在,已做好运行单元测试的准备工作。
生成和运行单元测试
既然已经定义了单元测试,您就可以生成和运行这些测试了。
生成和运行单元测试
在**“解决方案资源管理器”中右击解决方案节点,再单击“重新生成解决方案”**。
此步骤强制重新生成数据库项目和单元测试项目,以保证所有内容都是最新的。
在**“测试”菜单上,指向“窗口”,然后单击“测试列表编辑器”**。
**“测试视图”**窗口将列出若干测试。 默认情况下会创建名为 ManualTest1 和 TestMethod1 的测试。 名为 dbo_uspGetManagerEmployeesTest 的测试是在此演练中创建的。
选中对应于 dbo_ufpLeadingZeroTest 的复选框,右击它,再单击**“运行选中的测试”**。
在**“测试结果”**窗口中查看结果。
数据库项目将部署到独立开发环境中,并生成测试数据,然后将运行和通过测试。
签入挂起的更改
现在您已经定义了用于检测更改是否破坏数据库的单元测试,便可签入测试并与团队共享解决方案了。
与团队共享解决方案
在**“视图”菜单上,指向“其他窗口”,然后单击“挂起的更改”**。
将出现**“挂起的更改”**窗口。
在**“注释”**中,键入“定义的数据生成计划和基线单元测试”。
在**“挂起的更改”窗口中,单击工具栏上的“签入”**。
将数据库项目及其中包含的文件置于版本控制之下时,将出现**“签入进度”**对话框。 **“解决方案资源管理器”**中的图标将更新,以表明文件已签入到版本控制中。
后续步骤
现在您已经将解决方案签入到版本控制中,每个团队成员便可以处理为其分配的任务了。 每个人可在独立数据库开发环境中工作,直到所有更改可以共享为止。
在 演练:在独立开发环境中执行迭代数据库开发 中,您使用重构在独立开发环境中重命名数据库对象。 您在签入更改之前生成、部署和测试这些更改,然后其他团队成员可以将您的更改与自己的独立开发环境同步。
请参见
任务
概念
修订记录
日期 |
修订记录 |
原因 |
---|---|---|
添加了对 SQL Server 2008 R2 和 AdventureWorks2008R2 的支持。 还更正了客户反馈中指出的某些数据生成和单元测试问题。 |
SP1 功能更改。 |