6

SSMS で SQL クエリの簡単な単体テストを作成する方法はありますか? 私は T-SQL と SSMS にはかなり慣れていませんが、可能であれば、古い TDD の習慣をこの分野に取り入れたいと考えています。

たとえば、DDL を作成して複雑な関数などを作成する場合、(失敗した場合に) 実際に実行時に出力パネルにエラー メッセージを表示させる単体テストを含める方法が必要です。 . (これは、通常のプログラミング環境で「ビルドを壊す」ことに似ています。)

現在、構文的に正しい関数を作成し、F5 キーを押して実行すると、出力メッセージは次のようになります。

Command(s) completed successfully.

私が探しているのは、基本的な赤信号/青信号のテスト ケースをシミュレートするための単純な SQL トリックです。したがって、ユーザー定義関数が意図したとおりに動作している場合にのみ合格する一連のテスト ステートメントを記述します。そうしないと、次のようなエラー メッセージが表示されます。

Msg 207, Level 16, State 1, Line 2
Invalid statement.

これにより、失敗したテストにすぐにジャンプして、何が間違っていたかを確認できます。

これには「組み込み」のものがあるとは思いませんが、「偽造」できる方法はありますか?

更新: SS2012 で例外をスローできることを知りました。これは、この目的だけに使用できると確信していますが、残念ながら、今のところ SS2008 で立ち往生しています。SS2008に匹敵するものはありますか?

4

2 に答える 2

7

これらは私が推奨できる2つのフレームワークです

TST

http://tst.codeplex.com/

TST を使用した SQL Server コードのテスト

http://www.infoq.com/articles/tst-sql-server

tSQLt

http://tsqlt.org/

SQL テスト (tSQLt のランナー)

http://www.red-gate.com/products/sql-development/sql-test/

更新 1

あなたの答えを読んで、次のダンプが役に立つかもしれません。

TRY CATCH は SQL Server 2005 で導入されました (このため、2005 年より古いものを調べるべきではありません)。行番号を含む、ダンプに記載されているストアド プロシージャを使用して、実際に例外を (再) スローできます。SQL Server 2012では、14年後にTsqlを堅牢な言語にすることに言及したように、彼らは(ついに!)throwを導入しました。

これが私のダンプです。いつかクリーンアップする必要があるので、よりコピーペーストしやすくなります。

SET XACT_ABORT ON
SET CONCAT_NULL_YIELDS_NULL OFF

DECLARE @message varchar ( max ) 
DECLARE @who varchar ( 255 ) 
set @who = OBJECT_NAME(@@PROCID) -- name of the currently executing sproc

BEGIN TRY

-- ======================================================================================
SET @message = 'HELLO'
EXEC Log @who, @message

         ....

-- ======================================================================================
SET @message = 'GOODBYE'
EXEC Log @who, @message

END TRY

BEGIN CATCH


        -- ======================================================================================
--If an error generated in a TRY block causes the state of the current transaction to be invalidated, the transaction is classified as an uncommittable transaction.
--An error that ordinarily ends a transaction outside a TRY block causes a transaction to enter an uncommittable state when the error occurs inside a TRY block.
-- http://msdn.microsoft.com/en-us/library/ms175976.aspx
       if XACT_STATE() = -1 rollback;

    -- ======================================================================================
SET @message = 'Rolling Back transaction if present'
EXEC Log @who, @message

     -- Its important to rollback the transaction at the very start of the catch.
-- Otherwise the records that are written to the log will also be roll backed.

IF @@TRANCOUNT > 0 
BEGIN
ROLLBACK TRAN 
END

-- ======================================================================================
SET @message = 'Error Occured '
set @message = @message + ' ERROR_NUMBER() : ' + cast(ERROR_NUMBER() as varchar(max))
set @message = @message + ' ERROR_SEVERITY() : ' + cast(ERROR_SEVERITY() as varchar(max))
set @message = @message + ' ERROR_STATE() : ' + cast(ERROR_STATE() as varchar(max))
set @message = @message + ' ERROR_PROCEDURE() : ' +cast(ERROR_PROCEDURE() as varchar(max))
set @message = @message + ' ERROR_LINE() : ' + cast(ERROR_LINE() as varchar(max))
set @message = @message + ' ERROR_MESSAGE() : ' + cast(ERROR_MESSAGE() as varchar(max))

EXEC Log @who, @message

  exec usp_RethrowError


END CATCH


Error logging sproc and table

CREATE PROCEDURE [dbo].[Log]
(
@who varchar(255),
@message varchar(max)
)
AS

SET XACT_ABORT ON
SET CONCAT_NULL_YIELDS_NULL OFF

INSERT INTO [ApplicationLog]
(
[Date],
[Level],
[Logger],
[Host],
[Message]
)
VALUES
(
getDate(),
'INFO',
@who,
'dummy',
@message
)

CREATE TABLE [dbo].[ApplicationLog] (
[Id]            [int] IDENTITY(1, 1) NOT NULL,
[Date]          [datetime] NOT NULL,
[Thread]        [varchar](255)  NULL,
[Level]         [varchar](50) NOT NULL,
[Logger]        [varchar](255)  NOT NULL,
[Host]          [varchar](50)  NOT NULL,
[Message]       [varchar](max)  NOT NULL,
[Exception]     [varchar](max) NULL
)


Rethrow an exception

ALTER PROCEDURE [dbo].[usp_RethrowError]
 -- BOL contains a good example of that, there is a stored procedure called usp_RethrowError

AS -- Return if there is no error information to retrieve.

SET XACT_ABORT ON
SET CONCAT_NULL_YIELDS_NULL OFF

IF ERROR_NUMBER() IS NULL 
  RETURN ;

DECLARE @ErrorMessage NVARCHAR(4000),
  @ErrorNumber INT,
  @ErrorSeverity INT,
  @ErrorState INT,
  @ErrorLine INT,
  @ErrorProcedure NVARCHAR(200) ;

    -- Assign variables to error-handling functions that 
    -- capture information for RAISERROR.
SELECT  @ErrorNumber = ERROR_NUMBER(), @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE(), @ErrorLine = ERROR_LINE(),
        @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-') ;

    -- Building the message string that will contain original
    -- error information.
SELECT  @ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' +
        'Message: ' + ERROR_MESSAGE() ;

    -- Raise an error: msg_str parameter of RAISERROR will contain
    -- the original error information.
RAISERROR (@ErrorMessage, @ErrorSeverity, 1, @ErrorNumber, -- parameter: original error number.
  @ErrorSeverity, -- parameter: original error severity.
  @ErrorState, -- parameter: original error state.
  @ErrorProcedure, -- parameter: original error procedure name.
  @ErrorLine-- parameter: original error line number.
        ) ;
于 2012-06-27T22:08:55.823 に答える
0

さて、私は自分の質問に対する可能な解決策を見つけました: RAISERROR。これはある程度「機能」し (少なくとも私が思い描いていた方法では)、次のような基本的なテストを作成できます。

IF dbo.myTestedFunction(@parm) != @myExpectedResult
    RAISERROR('>> Unit Test FAILED! -- %d, 11, 0, @parm)

風変わりですが、最初の行にいくつかの偽の情報がありますが、クリックして問題のあるコード行 (私の場合は失敗したユニット テスト) にジャンプできるエラー メッセージが表示されます。

于 2012-06-27T23:23:11.987 に答える