tSQLt - проверить, что столбец выводится хранимой процедурой

Я очень плохо знаком с tSQLt и испытываю трудности с тем, что должно быть очень простым тестом.

Я добавил столбец в инструкцию SELECT, выполняемую в хранимой процедуре.

Как проверить в тесте tSQLt, что столбец включен в набор результатов этой хранимой процедуры?

2 ответа

Решение

Как правило, при добавлении столбца к выводу хранимой процедуры вы хотите проверить, что столбец существует и заполнен правильными данными. Поскольку мы собираемся убедиться, что столбец заполнен одними и теми же данными, мы можем разработать тест, который будет делать именно это:

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: http://tsqlt.org/user-guide/isolating-dependencies/

Другой вариант, если вас просто интересует структура вывода, а не его содержимое (и вы работаете на SQL2012 или более поздней версии), - это использовать sys.dm_exec_describe_first_result_set_for_object в вашем тесте.

Этот dmo (динамический объект управления) возвращает различную информацию о первом наборе результатов, возвращаемом для данного объекта.

В моем примере ниже я использовал только несколько столбцов, возвращаемых этим dmo, но другие доступны, если, например, ваш вывод включает десятичные типы данных.

В этом тесте я заполняю временную таблицу (#expected) с информацией о том, как я ожидаю, что будет возвращен каждый столбец - например, имя, тип данных и обнуляемость.

Затем я выбираю эквивалентные столбцы из dmo в другую временную таблицу (#actual).

Наконец то пользуюсь tSQLt.AssertEqualsTable сравнить содержимое двух таблиц.

Сказав все это, в то время как я часто пишу тесты для проверки структуры представлений или таблиц (используя tSQLt.AssertResultSetsHaveSameMetaData), Я никогда не обнаруживал необходимости просто проверять контракт набора результатов для процедур. Деннис прав, вам, как правило, было бы интересно заявить, что различные столбцы в вашем наборе результатов заполнены правильными значениями, и к тому времени, когда вы охватите эту функциональность, вы все равно должны были охватить каждый столбец.

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+]'
Другие вопросы по тегам