Запуск tsqlt assert внутри курсора

Я пишу 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;

выдает сообщение о том, что тесты не выполнялись Как я могу подать в суд на курсор, чтобы уменьшить количество тестов? Или есть другой подход, который я должен рассмотреть?

2 ответа

Решение

В конце концов, я достиг конечной цели за пару шагов: 1. Переместить оператор assert за пределы курсора 2. Создать временную таблицу cased с записями 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. За пределами курсора я установил новый параметр, который принимает любые ошибки, если они существуют, или "проходит", если они не существуют.

SET @Result = ( SELECT DISTINCT TOP 1
                        TestStatus
                FROM    #ActualAssert
                ORDER BY TestStatus ASC
              );

4. Затем я изменил assert, чтобы он не выполнялся, если @result отличается от 'Pass'

EXEC tSQLt.AssertEqualsString @Expected = N'Pass', -- nvarchar(max)
    @Actual = @Result, @Message = N''; -- nvarchar(max)

** Примечание: я заменяю предыдущие существующие и ожидаемые временные таблицы на таблицы переменных

Я бы посоветовал вам написать что-то, что называется параметризованным тестом.

tSQLt (пока) не имеет встроенной поддержки для этого, но есть простой обходной путь:

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

Вы также называете эту процедуру именем, которое не начинается с "test" (но находится в той же схеме).

Затем вы пишете один реальный тест для каждого конкретного случая, каждый из которых состоит из одной строки: выполнение вашей параметризованной процедуры.

Это приведет к тестам, которые намного легче понять, чем ваш текущий подход. И, кроме того, если один из них выходит из строя, вы сразу знаете, какой.

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

Другие вопросы по тегам