演练:使用自定义测试条件来验证存储过程的结果
在本功能扩展演练中,您将创建一个测试条件,并且将通过创建 SQL Server 单元测试来验证其功能。此过程包括为该测试条件创建一个类库项目,并且对该项目进行签名和安装它。如果您已具有一个要更新的测试条件,请参见如何:将 Visual Studio 2010 自定义测试条件从早期版本升级到 SQL Server Data Tools。
本演练演示以下任务:
如何创建测试条件。
如何用强名称为程序集签名。
如何添加对项目的必需的引用。
如何生成测试条件。
如何安装新的测试条件。
如何测试新的测试条件。
要完成本演练,您必须具有含 Visual Studio 2010 的最新版本的 Visual Studio 2012 或 SQL Server Data Tools。有关更多信息,请参见安装 SQL Server 数据工具。
创建自定义测试条件
首先,您将创建一个类库。
在**“文件”菜单上,单击“新建”,然后单击“项目”**。
在**“新建项目”对话框中的“项目类型”**下,单击 Visual C#。
在**“模板”下,选择“类库”**。
在**“名称”文本框中,键入 ColumnCountCondition,然后单击“确定”**。
接下来,对该项目进行签名。
在**“项目”菜单上,单击“ColumnCountCondition 属性”**。
在**“签名”选项卡上,选中“为程序集签名”**复选框。
在“选择强名称密钥文件”框中,单击“<新建...>”。
**“创建强名称密钥”**对话框随即出现。
在**“密钥文件名称”**框中,键入 SampleKey。
键入并确认密码,然后单击**“确定”**。生成您的解决方案时,将使用该密钥文件对程序集进行签名。
在“文件”菜单上,单击“全部保存”。
在“生成”菜单上,单击“生成解决方案”。
接下来,您将添加对项目的必需的引用。
在**“解决方案资源管理器”**中选择 ColumnCountCondition 项目。
在**“项目”菜单中,单击“添加引用”以便显示“添加引用”**对话框。
选择 .NET 选项卡。
在**“组件名称”列中,找到并选择 System.ComponentModel.Composition 组件。在选择该组件后,单击“确定”**。
添加所需的程序集引用。右键单击项目节点,然后单击“添加引用”。单击“浏览”并导航到 C:\Program Files (x86)\MicrosoftSQL Server\110\DAC\Bin 文件夹。选择 Microsoft.Data.Tools.Schema.Sql.dll 并单击“添加”,然后单击“确定”。
在**“项目”菜单上,单击“卸载项目”**。
在“解决方案资源管理器”中右键单击该项目,然后选择“编辑 .csproj”。
在导入 Microsoft.CSharp.targets 后添加以下 Import 语句:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\SSDT\Microsoft.Data.Tools.Schema.Sql.UnitTesting.targets" Condition="'$(VisualStudioVersion)' == ''" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.Sql.UnitTesting.targets" Condition="'$(VisualStudioVersion)' != ''" />
保存并关闭该文件。在**“解决方案资源管理器”中右键单击该项目,然后选择“重新加载项目”**。
所需引用将显示在**“解决方案资源管理器”中该项目的“引用”**节点下。
创建 ResultSetColumnCountCondition 类
现在,您将 Class1 重命名为 ResultSetColumnCountCondition,并且从 TestCondition 派生它。ResultSetColumnCountCondition 类是一个简单的测试条件,该条件验证在结果集中返回的列数。您可以使用此条件确保某一存储过程的协定是正确的。
在**“解决方案资源管理器”中,右键单击 Class1.cs,单击“重命名”**,然后键入 ResultSetColumnCountCondition.cs。
单击**“是”**以便确认重命名对 Class1 的所有引用。
打开 ResultSetColumnCountCondition.cs 文件并且将以下 using 语句添加到该文件:
using System; using System.ComponentModel; using System.Data; using System.Data.Common; using Microsoft.Data.Tools.Schema.Sql.UnitTesting; using Microsoft.Data.Tools.Schema.Sql.UnitTesting.Conditions; namespace ColumnCountCondition { public class ResultSetColumnCountCondition
从 TestCondition 派生该类:
public class ResultSetColumnCountCondition : TestCondition
添加 ExportTestConditionAttribute。有关 如何:为 SQL Server 单元测试设计器创建测试条件 的更多信息,请参见ExportTestConditionAttribute。
[ExportTestCondition("ResultSet Column Count", typeof(ResultSetColumnCountCondition))] public class ResultSetColumnCountCondition : TestCondition
创建成员变量和构造函数:
private int _resultSet; private int _count; private int _batch; public ResultSetColumnCountCondition() { _resultSet = 1; _count = 0; _batch = 1; }
重写 Assert 方法。该方法包含 IDbConnection 参数(表示与数据库的连接)以及 SqlExecutionResult 参数。该方法使用 DataSchemaException 来处理错误:
//method you need to override //to perform the condition verification public override void Assert(DbConnection validationConnection, SqlExecutionResult[] results) { //call base for parameter validation base.Assert(validationConnection, results); //verify batch exists if (results.Length < _batch) throw new DataException(String.Format("Batch {0} does not exist", _batch)); SqlExecutionResult result = results[_batch - 1]; //verify resultset exists if (result.DataSet.Tables.Count < ResultSet) throw new DataException(String.Format("ResultSet {0} does not exist", ResultSet)); DataTable table = result.DataSet.Tables[ResultSet - 1]; //actual condition verification //verify resultset column count matches expected if (table.Columns.Count != Count) throw new DataException(String.Format( "ResultSet {0}: {1} columns did not match the {2} columns expected", ResultSet, table.Columns.Count, Count)); } Add the following method, which overrides the ToString method: C# //this method is called to provide the string shown in the //test conditions panel grid describing what the condition tests public override string ToString() { return String.Format( "Condition fails if ResultSet {0} does not contain {1} columns", ResultSet, Count); }
通过使用 CategoryAttribute、DisplayNameAttribute 和 DescriptionAttribute 特性,添加以下测试条件属性:
//below are the test condition properties //that are exposed to the user in the property browser #region Properties //property specifying the resultset for which //you want to check the column count [Category("Test Condition")] [DisplayName("ResultSet")] [Description("ResultSet Number")] public int ResultSet { get { return _resultSet; } set { //basic validation if (value < 1) throw new ArgumentException("ResultSet cannot be less than 1"); _resultSet = value; } } //property specifying //expected column count [Category("Test Condition")] [DisplayName("Count")] [Description("Column Count")] public int Count { get { return _count; } set { //basic validation if (value < 0) throw new ArgumentException("Count cannot be less than 0"); _count = value; } } #endregion
最终的代码列表如下所示:
using System;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using Microsoft.Data.Tools.Schema.Sql.UnitTesting;
using Microsoft.Data.Tools.Schema.Sql.UnitTesting.Conditions;
namespace ColumnCountCondition
{
[ExportTestCondition("ResultSet Column Count", typeof(ResultSetColumnCountCondition))]
public class ResultSetColumnCountCondition : TestCondition
{
private int _resultSet;
private int _count;
private int _batch;
public ResultSetColumnCountCondition()
{
_resultSet = 1;
_count = 0;
_batch = 1;
}
//method you need to override
//to perform the condition verification
public override void Assert(DbConnection validationConnection, SqlExecutionResult[] results)
{
//call base for parameter validation
base.Assert(validationConnection, results);
//verify batch exists
if (results.Length < _batch)
throw new DataException(String.Format("Batch {0} does not exist", _batch));
SqlExecutionResult result = results[_batch - 1];
//verify resultset exists
if (result.DataSet.Tables.Count < ResultSet)
throw new DataException(String.Format("ResultSet {0} does not exist", ResultSet));
DataTable table = result.DataSet.Tables[ResultSet - 1];
//actual condition verification
//verify resultset column count matches expected
if (table.Columns.Count != Count)
throw new DataException(String.Format(
"ResultSet {0}: {1} columns did not match the {2} columns expected",
ResultSet, table.Columns.Count, Count));
}
//this method is called to provide the string shown in the
//test conditions panel grid describing what the condition tests
public override string ToString()
{
return String.Format(
"Condition fails if ResultSet {0} does not contain {1} columns",
ResultSet, Count);
}
//below are the test condition properties
//that are exposed to the user in the property browser
#region Properties
//property specifying the resultset for which
//you want to check the column count
[Category("Test Condition")]
[DisplayName("ResultSet")]
[Description("ResultSet Number")]
public int ResultSet
{
get { return _resultSet; }
set
{
//basic validation
if (value < 1)
throw new ArgumentException("ResultSet cannot be less than 1");
_resultSet = value;
}
}
//property specifying
//expected column count
[Category("Test Condition")]
[DisplayName("Count")]
[Description("Column Count")]
public int Count
{
get { return _count; }
set
{
//basic validation
if (value < 0)
throw new ArgumentException("Count cannot be less than 0");
_count = value;
}
}
#endregion
}
}
接下来,我们将生成该项目。
编译项目并且安装您的测试条件
在“生成”菜单上,单击“生成解决方案”。
接下来,您要将程序集信息复制到 Extensions 目录中。在 Visual Studio 启动后,它会标识 %Program Files%\Microsoft Visual Studio \Common7\IDE\Extensions\Microsoft\SQLDB\TestConditions 目录和子目录中的任何扩展,并且使它们可供使用:
将 ColumnCountCondition.dll 程序集文件从输出目录复制到 %Program Files%\Microsoft Visual Studio \Common7\IDE\Extensions\Microsoft\SQLDB\TestConditions 目录。
默认情况下,已编译 .dll 文件的路径是 YourSolutionPath\YourProjectPath\bin\Debug 或 YourSolutionPath\YourProjectPath\bin\Release。
接下来,您将启动 Visual Studio 的一个新会话并且创建一个数据库项目。若要启动新 Visual Studio 会话并且创建数据库项目,请执行以下操作:
启动 Visual Studio 的第二个会话。
在**“文件”菜单上,单击“新建”,然后单击“项目”**。
在**“新建项目”**对话框的已安装模板列表中,选择 SQL Server 节点。
在详细信息窗格中,单击**“SQL Server 数据库项目”**。
在**“名称”文本框中,键入 SampleConditionDB,然后单击“确定”**。
接下来,我们需要创建一个单元测试。在新的测试类中创建 SQL Server 单元测试:
在**“测试”菜单中,单击“新建测试”以便显示“添加新测试”**对话框。
您也可以打开**“解决方案资源管理器”,右键单击某个测试项目,指向“添加”,然后单击“新建测试”**。
在模板列表中,单击**“SQL Server 单元测试”**。
在**“测试名称”**中,键入 SampleUnitTest。
在**“添加到测试项目”中,单击“创建新的 Visual C# 测试项目”。然后,单击“确定”以便显示“新建测试项目”**对话框。
为项目名称键入 SampleUnitTest。
单击**“取消”**以创建单元测试而不配置要使用数据库连接的测试项目。您的空白测试将出现在 SQL Server 单元测试设计器中。将 Visual C# 源代码文件添加到该测试项目中。
有关创建和配置具有数据库连接的数据库单元测试的更多信息,请参见如何:创建空的 SQL Server 单元测试。
单击**“单击此处以创建”**以完成单元测试的创建。您将看到在 SQL Server 项目中显示的新的测试条件。
说明 |
---|
|
查看新的测试条件:
在**“SQL Server 单元测试设计器”中的“测试条件”下,在“名称”**列下单击 inconclusiveCondition1 测试。
单击**“删除测试条件”**工具栏按钮以便删除 inconclusiveCondition1 测试。
单击**“测试条件”下拉列表,然后选择“ResultSet 列计数”**。
单击**“添加测试条件”**工具栏按钮以便添加您的自定义测试条件。
在**“属性”**窗口中,配置 Count、Enabled 和 ResultSet 属性。
有关更多信息,请参见如何:向 SQL Server 单元测试中添加条件。