运行 游标内的 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