我對tSQLt非常陌生,並且在真正應該做一個非常簡單的測試時遇到了一些困難。tSQLt - 測試某列是否由存儲過程輸出
我在存儲過程中執行的SELECT語句中添加了一列。
如何在tSQLt測試中測試該列是否包含在該存儲過程的結果集中?
我對tSQLt非常陌生,並且在真正應該做一個非常簡單的測試時遇到了一些困難。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: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+]'
非常感謝您的詳細回覆,但不幸的是我們仍然在爲此項目使用2008 R2。 – Neil 2014-10-17 16:23:49
謝謝丹尼斯。我認爲我試圖通過專注於一個新的列來複雜化問題,但是通過測試過程的輸出,該列將在默認情況下進行測試 – Neil 2014-10-20 08:13:00