====== tSQLt table tests ======
Inspired by [[https://github.com/sanderstad/PStSQLtTestGenerator]], thanks Sander!
===== Column attributes =====
CREATE VIEW tsqlt_test_utils.TableColumnAttributes
AS
SELECT
OBJECT_SCHEMA_NAME(o.[object_id]) AS TableSchema
, o.[name] AS TableName
, c.[name] AS ColumnName
, t.[name] AS TypeName
, c.max_length
, c.[precision]
, c.[scale]
, c.is_nullable
, CASE WHEN LOWER(hc.[description]) LIKE '%case-sensitive%' THEN 1 END AS IsCaseSensitive
, CASE c.is_identity WHEN 1 THEN 1 END AS is_identity
, pkc.index_column_id AS PkOrdinal
, dc.[definition] AS DefaultExpression
, cc.[definition] AS ComputedExpression
, cc.is_persisted
FROM sys.objects o
INNER JOIN sys.columns c ON c.[object_id] = o.[object_id]
INNER JOIN sys.types t ON t.user_type_id = c.user_type_id
LEFT JOIN sys.fn_helpcollations() hc ON hc.[name] = c.collation_name
LEFT JOIN sys.computed_columns cc
ON cc.[object_id] = c.[object_id]
AND cc.column_id = c.column_id
LEFT JOIN sys.default_constraints dc
ON dc.parent_object_id = c.[object_id]
AND dc.parent_column_id = c.column_id
LEFT JOIN sys.indexes pk
ON pk.[object_id] = o.[object_id]
AND pk.is_primary_key = 1
LEFT JOIN sys.index_columns pkc
ON pkc.[object_id] = pk.[object_id]
AND pkc.index_id = pk.index_id
AND pkc.column_id = c.column_id
WHERE o.[type] = 'U'
===== Generate tests =====
DECLARE @objectName NVARCHAR(500) = '[sprockit].[Event]';
DECLARE @testSchema NVARCHAR(128) = QUOTENAME(OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName))
+ '_' + OBJECT_NAME(OBJECT_ID(@objectName)));
DECLARE @columnNames NVARCHAR(MAX) = N'';
DECLARE @sql NVARCHAR(MAX);
/*
SELECT *
FROM tsqlt_test_utils.TableColumnAttributes
WHERE TableSchema = OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName))
AND TableName = OBJECT_NAME(OBJECT_ID(@objectName));
--*/
-- assert column existence
SET @columnNames = N'';
SELECT
@columnNames += '
, (''' + REPLACE(ColumnName, '''', '''''') + ''')'
FROM tsqlt_test_utils.TableColumnAttributes
WHERE TableSchema = OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName))
AND TableName = OBJECT_NAME(OBJECT_ID(@objectName));
SET @sql = 'CREATE PROCEDURE ' + @testSchema
+ '.[test Assert ' + OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName))
+ '.' + OBJECT_NAME(OBJECT_ID(@objectName))
+ ' has the correct columns]
AS
-- ARRANGE
SELECT [name]
INTO #expected
FROM sys.columns
WHERE 0 = 1;
INSERT INTO #expected (
[name]
) VALUES
' + SUBSTRING(@columnNames, 5, LEN(@columnNames)) + ';
-- ACT
SELECT [name]
INTO #actual
FROM sys.columns
WHERE [object_id] = OBJECT_ID('''+ @objectName + ''')
-- ASSERT
EXEC tSQLt.AssertEqualsTable
@Expected = ''#expected''
, @Actual = ''#actual'';'
PRINT @sql;
-- individual column tests
DECLARE @columnName NVARCHAR(128);
DECLARE _myCursor CURSOR LOCAL FOR
SELECT ColumnName
FROM tsqlt_test_utils.TableColumnAttributes
WHERE TableSchema = OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName))
AND TableName = OBJECT_NAME(OBJECT_ID(@objectName));
OPEN _myCursor
FETCH NEXT FROM _myCursor INTO @columnName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = N'';
SELECT @sql = 'CREATE PROCEDURE ' + @testSchema
+ '.[test Validate ' + OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName))
+ '.' + OBJECT_NAME(OBJECT_ID(@objectName)) + ' ' + @columnName + ']
AS
-- ARRANGE
DECLARE @tableSchema SYSNAME = ''' + OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName)) + ''';
DECLARE @tableName SYSNAME = ''' + OBJECT_NAME(OBJECT_ID(@objectName)) + ''';
DECLARE @columnName SYSNAME = ''' + @columnName + ''';
SELECT *
INTO #expected
FROM tsqlt_test_utils.TableColumnAttributes
WHERE 0 = 1;
INSERT INTO #expected (
[TableSchema]
, [TableName]
, [ColumnName]
, [TypeName]'
+ CASE WHEN max_length IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [max_length]' ELSE '' END
+ CASE WHEN [precision] IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [precision]' ELSE '' END
+ CASE WHEN [scale] IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [scale]' ELSE '' END
+ CASE WHEN is_nullable IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [is_nullable]' ELSE '' END
+ CASE WHEN IsCaseSensitive IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [IsCaseSensitive]' ELSE '' END
+ CASE WHEN is_identity IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [is_identity]' ELSE '' END
+ CASE WHEN PkOrdinal IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [PkOrdinal]' ELSE '' END
+ CASE WHEN DefaultExpression IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [DefaultExpression]' ELSE '' END
+ CASE WHEN ComputedExpression IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [ComputedExpression]' ELSE '' END
+ CASE WHEN is_persisted IS NOT NULL THEN CHAR(13) + CHAR(10) + ', [is_persisted]' ELSE '' END
+ '
) VALUES (
@tableSchema
, @tableName
, @columnName
, ''' + TypeName + ''''
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST(max_length AS NVARCHAR(10)), N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST([precision] AS NVARCHAR(10)), N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST([scale] AS NVARCHAR(10)), N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST(is_nullable AS NVARCHAR(10)), N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST(IsCaseSensitive AS NVARCHAR(10)), N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST(is_identity AS NVARCHAR(10)), N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST(PkOrdinal AS NVARCHAR(10)), N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ''' + REPLACE(DefaultExpression , '''', '''''') + '''', N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ''' + REPLACE(ComputedExpression, '''', '''''') + '''', N'')
+ COALESCE(CHAR(13) + CHAR(10) + ', ' + CAST(is_persisted AS NVARCHAR(10)), N'')
+ '
);
-- ACT
SELECT *
INTO #actual
FROM tsqlt_test_utils.TableColumnAttributes
WHERE TableName = @tableName
AND ColumnName = @columnName;
-- ASSERT
EXEC tSQLt.AssertEqualsTable
@Expected = ''#expected''
, @Actual = ''#actual'';'
FROM tsqlt_test_utils.TableColumnAttributes
WHERE TableSchema = OBJECT_SCHEMA_NAME(OBJECT_ID(@objectName))
AND TableName = OBJECT_NAME(OBJECT_ID(@objectName))
AND ColumnName = @columnName;
PRINT @sql;
FETCH NEXT FROM _myCursor INTO @columnName
END
CLOSE _myCursor
DEALLOCATE _myCursor
{{tag> tsqlt}}