运行 游标内的 tsqlt 断言
Running tsqlt assert inside a cursor
我正在针对一个可以 运行 针对各种参数值的过程编写 tsqlt。我最初构建了一个填充假表的 proc - 然后对每个可能的值进行 1 个 tsqlt 测试(最终进行了 35 个测试,每个测试都有效)。
我想做的是将这些减少为 1 个测试(因为它们实际上都在测试相同的功能 - 只是针对不同的值)。我想我可以用这样的游标来做到这一点:
---- Declare Sproc Variables
DECLARE @ReviewId INT;
DECLARE @SourceId INT = 1;
CREATE TABLE #Present
(
SubmissionReviewId INT ,
username VARCHAR(50)
);
CREATE TABLE #Expected
(
SubmissionReviewId INT ,
username VARCHAR(50)
);
--Create Cursor to loop through each active value
DECLARE review_id CURSOR
FOR
SELECT ReviewId
FROM reftype.Rev
WHERE IsActive = 1;
OPEN review_id;
FETCH NEXT FROM review_id
INTO @ReviewId;
WHILE @@FETCH_STATUS = 0
BEGIN
--Setup Fake Data according to the specified test condition
EXEC ut_DataSetupProc @ReviewId = @ReviewId;
-- Run set cutover Sproc
EXEC Procbeing Tested @ReviewId = @ReviewId,
@SourceId = 1, @Username = 'blah';
-- Confirm appropriate review is present in Submission Review Active
DELETE FROM #Present;
DELETE FROM #Expected;
INSERT INTO #Present
SELECT SubmissionReviewId ,
LastModifiedBy
FROM review.SubmissionReviewActive
ORDER BY SubmissionReviewId ,
LastModifiedBy;
/**********************Create table holding expected values***************************/
INSERT INTO #Expected
--This confirms active reviews that belong to other sections/sources remain unaffected
SELECT SubmissionReviewId ,
LastModifiedBy
FROM review.SubmissionReviewActive
WHERE ( ReviewId != @ReviewId )
OR ( SourceId != @SourceId )
UNION
SELECT sra.SubmissionReviewId ,
sra.LastModifiedBy
FROM review.SubmissionReviewActive sra
JOIN review.SubmissionReviewFutureActive srfa ON srfa.IssuerId = sra.IssuerId
AND srfa.ReviewId = sra.ReviewId
AND srfa.Version < sra.Version
WHERE sra.ReviewId = @ReviewId
AND sra.SourceId = @SourceId
UNION
SELECT srfa.SubmissionReviewId ,
'jmarina' AS LastModifiedBy
FROM review.SubmissionReviewFutureActive srfa
JOIN review.SubmissionReviewActive sra ON srfa.IssuerId = sra.IssuerId
AND srfa.ReviewId = sra.ReviewId
AND srfa.Version > sra.Version
WHERE sra.ReviewId = @ReviewId
AND srfa.SourceId = @SourceId
UNION
SELECT srfa.SubmissionReviewId ,
'blah' AS LastModifiedBy
FROM review.SubmissionReviewFutureActive srfa
WHERE srfa.ReviewId = @ReviewId
AND srfa.SourceId = @SourceId
AND srfa.IssuerId NOT IN (
SELECT IssuerId
FROM review.SubmissionReviewActive
WHERE ReviewId = @ReviewId
AND SourceId = @SourceId )
UNION
SELECT sra.SubmissionReviewId ,
sra.LastModifiedBy
FROM review.SubmissionReviewActive sra
WHERE sra.ReviewId = @ReviewId
AND sra.SourceId = @SourceId
AND IssuerId NOT IN (
SELECT IssuerId
FROM review.SubmissionReviewFutureActive
WHERE ReviewId = @ReviewId
AND SourceId = @SourceId )
ORDER BY SubmissionReviewId ,
LastModifiedBy;
/*************************************************************/
EXEC tSQLt.AssertEqualsTable @Expected = '#Expected',
@Actual = '#Present', @Message = N'', -- nvarchar(max)
@FailMsg = N'Active Status is not a match'; -- nvarchar(max)
FETCH NEXT FROM review_id
INTO @ReviewId;
END;
CLOSE review_id;
DEALLOCATE review_id;
DROP TABLE #Expected;
DROP TABLE #Present;
END;
但是,运行使用
EXEC proc name @ReviewId = @ReviewId;
生成一条消息说没有测试 运行。我如何起诉游标以减少我的测试次数?或者我应该考虑另一种方法吗?
我建议你写一个参数化测试。
tSQLt(还)没有对此的原生支持,但有一个简单的解决方法:
您首先正常编写一个测试。但不是对相关值进行硬编码,而是将它们作为过程的参数。 (对于数据集,可以使用 table 个参数。)
您还将该过程命名为不以 "test" 开头的名称(但存在于同一架构中)。
然后您为每个实际案例编写一个真实测试,每个测试包含一行:参数化过程的执行。
这将导致比您当前的方法更容易理解的测试。此外,如果其中之一失败,您会立即知道是哪一个。
附带说明:您总是希望对预期结果进行硬编码。您当前的代码很复杂。您希望尽量减少测试本身可能出错的事情。确实,您的目标应该是一眼就能理解的测试。
最后我通过几个步骤实现了最终目标:
1.将assert语句移到游标之外
2. 创建了 'cased' temp table 和 pass/fail 条记录
INSERT INTO #ActualAssert
SELECT p.SubmissionReviewId,e.SubmissionReviewId,
CASE WHEN ( e.SubmissionReviewId IS NULL
OR p.SubmissionReviewId IS NULL
) THEN 'Fail'
ELSE 'Pass'
END
FROM @Present p
LEFT JOIN @Expected e ON e.SubmissionReviewId = p.SubmissionReviewId
UNION
SELECT p.SubmissionReviewId,e.SubmissionReviewId ,
CASE WHEN ( e.SubmissionReviewId IS NULL
OR p.SubmissionReviewId IS NULL
) THEN 'Fail'
ELSE 'Pass'
END
FROM @Present p
RIGHT JOIN @Expected e ON e.SubmissionReviewId = p.SubmissionReviewId;
3。在游标之外,我设置了一个新参数,如果存在则接受任何失败,如果不存在则接受 'pass'
SET @Result = ( SELECT DISTINCT TOP 1
TestStatus
FROM #ActualAssert
ORDER BY TestStatus ASC
);
4。然后我修改了断言,如果@result 不是 'Pass'
则失败
EXEC tSQLt.AssertEqualsString @Expected = N'Pass', -- nvarchar(max)
@Actual = @Result, @Message = N''; -- nvarchar(max)
** 注释我将以前的现在和预期的温度 tables 更改为变量 tables
我正在针对一个可以 运行 针对各种参数值的过程编写 tsqlt。我最初构建了一个填充假表的 proc - 然后对每个可能的值进行 1 个 tsqlt 测试(最终进行了 35 个测试,每个测试都有效)。
我想做的是将这些减少为 1 个测试(因为它们实际上都在测试相同的功能 - 只是针对不同的值)。我想我可以用这样的游标来做到这一点:
---- Declare Sproc Variables
DECLARE @ReviewId INT;
DECLARE @SourceId INT = 1;
CREATE TABLE #Present
(
SubmissionReviewId INT ,
username VARCHAR(50)
);
CREATE TABLE #Expected
(
SubmissionReviewId INT ,
username VARCHAR(50)
);
--Create Cursor to loop through each active value
DECLARE review_id CURSOR
FOR
SELECT ReviewId
FROM reftype.Rev
WHERE IsActive = 1;
OPEN review_id;
FETCH NEXT FROM review_id
INTO @ReviewId;
WHILE @@FETCH_STATUS = 0
BEGIN
--Setup Fake Data according to the specified test condition
EXEC ut_DataSetupProc @ReviewId = @ReviewId;
-- Run set cutover Sproc
EXEC Procbeing Tested @ReviewId = @ReviewId,
@SourceId = 1, @Username = 'blah';
-- Confirm appropriate review is present in Submission Review Active
DELETE FROM #Present;
DELETE FROM #Expected;
INSERT INTO #Present
SELECT SubmissionReviewId ,
LastModifiedBy
FROM review.SubmissionReviewActive
ORDER BY SubmissionReviewId ,
LastModifiedBy;
/**********************Create table holding expected values***************************/
INSERT INTO #Expected
--This confirms active reviews that belong to other sections/sources remain unaffected
SELECT SubmissionReviewId ,
LastModifiedBy
FROM review.SubmissionReviewActive
WHERE ( ReviewId != @ReviewId )
OR ( SourceId != @SourceId )
UNION
SELECT sra.SubmissionReviewId ,
sra.LastModifiedBy
FROM review.SubmissionReviewActive sra
JOIN review.SubmissionReviewFutureActive srfa ON srfa.IssuerId = sra.IssuerId
AND srfa.ReviewId = sra.ReviewId
AND srfa.Version < sra.Version
WHERE sra.ReviewId = @ReviewId
AND sra.SourceId = @SourceId
UNION
SELECT srfa.SubmissionReviewId ,
'jmarina' AS LastModifiedBy
FROM review.SubmissionReviewFutureActive srfa
JOIN review.SubmissionReviewActive sra ON srfa.IssuerId = sra.IssuerId
AND srfa.ReviewId = sra.ReviewId
AND srfa.Version > sra.Version
WHERE sra.ReviewId = @ReviewId
AND srfa.SourceId = @SourceId
UNION
SELECT srfa.SubmissionReviewId ,
'blah' AS LastModifiedBy
FROM review.SubmissionReviewFutureActive srfa
WHERE srfa.ReviewId = @ReviewId
AND srfa.SourceId = @SourceId
AND srfa.IssuerId NOT IN (
SELECT IssuerId
FROM review.SubmissionReviewActive
WHERE ReviewId = @ReviewId
AND SourceId = @SourceId )
UNION
SELECT sra.SubmissionReviewId ,
sra.LastModifiedBy
FROM review.SubmissionReviewActive sra
WHERE sra.ReviewId = @ReviewId
AND sra.SourceId = @SourceId
AND IssuerId NOT IN (
SELECT IssuerId
FROM review.SubmissionReviewFutureActive
WHERE ReviewId = @ReviewId
AND SourceId = @SourceId )
ORDER BY SubmissionReviewId ,
LastModifiedBy;
/*************************************************************/
EXEC tSQLt.AssertEqualsTable @Expected = '#Expected',
@Actual = '#Present', @Message = N'', -- nvarchar(max)
@FailMsg = N'Active Status is not a match'; -- nvarchar(max)
FETCH NEXT FROM review_id
INTO @ReviewId;
END;
CLOSE review_id;
DEALLOCATE review_id;
DROP TABLE #Expected;
DROP TABLE #Present;
END;
但是,运行使用
EXEC proc name @ReviewId = @ReviewId;
生成一条消息说没有测试 运行。我如何起诉游标以减少我的测试次数?或者我应该考虑另一种方法吗?
我建议你写一个参数化测试。
tSQLt(还)没有对此的原生支持,但有一个简单的解决方法:
您首先正常编写一个测试。但不是对相关值进行硬编码,而是将它们作为过程的参数。 (对于数据集,可以使用 table 个参数。)
您还将该过程命名为不以 "test" 开头的名称(但存在于同一架构中)。
然后您为每个实际案例编写一个真实测试,每个测试包含一行:参数化过程的执行。
这将导致比您当前的方法更容易理解的测试。此外,如果其中之一失败,您会立即知道是哪一个。
附带说明:您总是希望对预期结果进行硬编码。您当前的代码很复杂。您希望尽量减少测试本身可能出错的事情。确实,您的目标应该是一眼就能理解的测试。
最后我通过几个步骤实现了最终目标: 1.将assert语句移到游标之外 2. 创建了 'cased' temp table 和 pass/fail 条记录
INSERT INTO #ActualAssert
SELECT p.SubmissionReviewId,e.SubmissionReviewId,
CASE WHEN ( e.SubmissionReviewId IS NULL
OR p.SubmissionReviewId IS NULL
) THEN 'Fail'
ELSE 'Pass'
END
FROM @Present p
LEFT JOIN @Expected e ON e.SubmissionReviewId = p.SubmissionReviewId
UNION
SELECT p.SubmissionReviewId,e.SubmissionReviewId ,
CASE WHEN ( e.SubmissionReviewId IS NULL
OR p.SubmissionReviewId IS NULL
) THEN 'Fail'
ELSE 'Pass'
END
FROM @Present p
RIGHT JOIN @Expected e ON e.SubmissionReviewId = p.SubmissionReviewId;
3。在游标之外,我设置了一个新参数,如果存在则接受任何失败,如果不存在则接受 'pass'
SET @Result = ( SELECT DISTINCT TOP 1
TestStatus
FROM #ActualAssert
ORDER BY TestStatus ASC
);
4。然后我修改了断言,如果@result 不是 'Pass'
则失败EXEC tSQLt.AssertEqualsString @Expected = N'Pass', -- nvarchar(max)
@Actual = @Result, @Message = N''; -- nvarchar(max)
** 注释我将以前的现在和预期的温度 tables 更改为变量 tables