tSQLt—测试存储过程是否输出列

tSQLt—测试存储过程是否输出列,tsqlt,Tsqlt,我对tSQLt非常陌生,在一个非常简单的测试中遇到了一些困难 我在存储过程中执行的SELECT语句中添加了一列 如何在tSQLt测试中测试该列是否包含在该存储过程的结果集中?通常,在向存储过程的输出中添加列时,您会希望测试该列是否存在并且填充了正确的数据。因为我们要确保列中填充了相同的数据,所以我们可以设计一个测试来实现这一点: CREATE PROCEDURE MyTests.[test stored procedure values MyNewColumn correctly] AS BEG

我对tSQLt非常陌生,在一个非常简单的测试中遇到了一些困难

我在存储过程中执行的SELECT语句中添加了一列


如何在tSQLt测试中测试该列是否包含在该存储过程的结果集中?

通常,在向存储过程的输出中添加列时,您会希望测试该列是否存在并且填充了正确的数据。因为我们要确保列中填充了相同的数据,所以我们可以设计一个测试来实现这一点:

CREATE PROCEDURE MyTests.[test stored procedure values MyNewColumn correctly]
AS
BEGIN
  -- Create Actual and Expected table to hold the actual results of MyProcedure 
  -- and the results that I expect
  CREATE TABLE MyTests.Actual (FirstColumn INT, MyNewColumn INT);
  CREATE TABLE MyTests.Expected (FirstColumn INT, MyNewColumn INT);

  -- Capture the results of MyProcedure into the Actual table
  INSERT INTO MyTests.Actual
  EXEC MySchema.MyProcedure;

  -- Create the expected output
  INSERT INTO MyTests.Expected (FirstColumn, MyNewColumn)
  VALUES (7, 12);
  INSERT INTO MyTests.Expected (FirstColumn, MyNewColumn)
  VALUES (25, 99);


  -- Check that Expected and Actual tables contain the same results
  EXEC tSQLt.AssertEqualsTable 'MyTests.Expected', 'MyTests.Actual';
END;

通常,您正在测试的存储过程依赖于其他表或其他存储过程。因此,您也应该熟悉FakeTable和SpyProcedure:

如果您只对输出的结构感兴趣,而不是内容感兴趣,并且运行在SQL2012或更高版本上,那么另一个选项是在测试中使用sys.dm\u exec\u description\u first\u result\u set\u对象

此dmo动态管理对象返回关于为给定对象返回的第一个结果集的各种信息

在下面的示例中,我只使用了此dmo返回的一些列,但如果您的输出包含十进制数据类型,则其他列可用

在这个测试中,我将填充一个临时表,其中包含关于如何返回每个列的信息,例如名称、数据类型和可空性

然后,我从dmo中选择等效的列到另一个临时表中

最后,我使用tSQLt.AssertEqualsTable比较两个表的内容

话虽如此,尽管我经常使用tSQLt.AssertResultSetsHaveSameMetaData编写测试以验证视图或表的结构,但我从未发现只需要测试过程的结果集契约。Dennis是正确的,您通常会对断言结果集中的各个列都填充了正确的值感兴趣,并且在介绍该功能时,您应该已经介绍了所有列

if object_id('dbo.myTable') is not null drop table dbo.myTable;
go
if object_id('dbo.myTable') is null
begin
    create table dbo.myTable
    (
      Id int not null primary key
    , ColumnA varchar(32) not null
    , ColumnB varchar(64) null
    )
end
go
if object_id('dbo.myProcedure') is not null drop procedure dbo.myProcedure;
go
create procedure dbo.myProcedure
as
begin
    select Id, ColumnA, ColumnB from dbo.myTable;
end
go

exec tSQLt.NewTestClass @ClassName = 'myTests';

if object_id('[myTests].[test result set on SQL2012+]') is not null drop procedure [myTests].[test result set on SQL2012+];
go
create procedure [myTests].[test result set on SQL2012+]
as
begin
    ; with expectedCte (name, column_ordinal, system_type_name, is_nullable)
    as
    (
        -- The first row sets up the data types for the #expected but is excluded from the expected results
                  select cast('' as nvarchar(200)), cast(0 as int), cast('' as nvarchar(200)), cast(0 as bit)
        -- This is the result we are expecting to see
        union all select 'Id', 1, 'int', 0
        union all select 'ColumnA', 2, 'varchar(32)', 0
        union all select 'ColumnB', 3, 'varchar(64)', 1
    )
    select * into #expected from expectedCte where column_ordinal > 0;

    --! Act
    select
          name
        , column_ordinal
        , system_type_name
        , is_nullable
    into
        #actual
    from
        sys.dm_exec_describe_first_result_set_for_object(object_id('dbo.myProcedure'), 0);

    --! Assert
    exec tSQLt.AssertEqualsTable '#expected', '#actual';
end
go
exec tSQLt.Run '[myTests].[test result set on SQL2012+]'

非常感谢您的详细答复,但不幸的是,我们仍在使用2008 R2进行此项目。谢谢丹尼斯。我想我试图通过集中在一个新列上使问题过于复杂,但是通过测试过程的输出,默认情况下将测试该列